/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Specialized; using System.Collections.Generic; using Apache.NMS.Util; namespace Apache.NMS.ActiveMQ.Commands { /// /// Summary description for ActiveMQDestination. /// public abstract class ActiveMQDestination : BaseDataStructure, IDestination { /// /// Topic Destination object /// public const int ACTIVEMQ_TOPIC = 1; /// /// Temporary Topic Destination object /// public const int ACTIVEMQ_TEMPORARY_TOPIC = 2; /// /// Queue Destination object /// public const int ACTIVEMQ_QUEUE = 3; /// /// Temporary Queue Destination object /// public const int ACTIVEMQ_TEMPORARY_QUEUE = 4; /// /// prefix for Advisory message destinations /// public const String ADVISORY_PREFIX = "ActiveMQ.Advisory."; /// /// prefix for consumer advisory destinations /// public const String CONSUMER_ADVISORY_PREFIX = ADVISORY_PREFIX + "Consumers."; /// /// prefix for producer advisory destinations /// public const String PRODUCER_ADVISORY_PREFIX = ADVISORY_PREFIX + "Producers."; /// /// prefix for connection advisory destinations /// public const String CONNECTION_ADVISORY_PREFIX = ADVISORY_PREFIX + "Connections."; /// /// The default target for ordered destinations /// public const String DEFAULT_ORDERED_TARGET = "coordinator"; private const String TEMP_PREFIX = "{TD{"; private const String TEMP_POSTFIX = "}TD}"; private const String COMPOSITE_SEPARATOR = ","; private String physicalName = ""; private StringDictionary options = null; // Cached transient data private bool exclusive; private bool ordered; private bool advisory; private String orderedTarget = DEFAULT_ORDERED_TARGET; /// /// The Default Constructor /// protected ActiveMQDestination() { } /// /// Construct the Destination with a defined physical name; /// /// protected ActiveMQDestination(String name) { setPhysicalName(name); //this.advisory = name != null && name.StartsWith(ADVISORY_PREFIX); } public bool IsTopic { get { int destinationType = GetDestinationType(); return ACTIVEMQ_TOPIC == destinationType || ACTIVEMQ_TEMPORARY_TOPIC == destinationType; } } public bool IsQueue { get { int destinationType = GetDestinationType(); return ACTIVEMQ_QUEUE == destinationType || ACTIVEMQ_TEMPORARY_QUEUE == destinationType; } } public bool IsTemporary { get { int destinationType = GetDestinationType(); return ACTIVEMQ_TEMPORARY_QUEUE == destinationType || ACTIVEMQ_TEMPORARY_TOPIC == destinationType; } } /// /// Dictionary of name/value pairs representing option values specified /// in the URI used to create this Destination. A null value is returned /// if no options were specified. /// internal StringDictionary Options { get { return this.options; } } private void setPhysicalName(string name) { this.physicalName = name; int p = name.IndexOf('?'); if(p >= 0) { String optstring = physicalName.Substring(p + 1); this.physicalName = name.Substring(0, p); options = URISupport.ParseQuery(optstring); } } /// /// /// Returns the advisory. public bool IsAdvisory() { return advisory; } /// /// /// The advisory to set. public void SetAdvisory(bool advisory) { this.advisory = advisory; } /// /// /// true if this is a destination for Consumer advisories public bool IsConsumerAdvisory() { return IsAdvisory() && physicalName.StartsWith(CONSUMER_ADVISORY_PREFIX); } /// /// /// true if this is a destination for Producer advisories public bool IsProducerAdvisory() { return IsAdvisory() && physicalName.StartsWith(PRODUCER_ADVISORY_PREFIX); } /// /// /// true if this is a destination for Connection advisories public bool IsConnectionAdvisory() { return IsAdvisory() && physicalName.StartsWith(CONNECTION_ADVISORY_PREFIX); } /// /// /// Returns the exclusive. public bool IsExclusive() { return exclusive; } /// /// /// The exclusive to set. public void SetExclusive(bool exclusive) { this.exclusive = exclusive; } /// /// /// Returns the ordered. public bool IsOrdered() { return ordered; } /// /// /// The ordered to set. public void SetOrdered(bool ordered) { this.ordered = ordered; } /// /// /// Returns the orderedTarget. public String GetOrderedTarget() { return orderedTarget; } /// /// /// The orderedTarget to set. public void SetOrderedTarget(String orderedTarget) { this.orderedTarget = orderedTarget; } /// /// A helper method to return a descriptive string for the topic or queue /// /// /// a descriptive string for this queue or topic public static String Inspect(ActiveMQDestination destination) { if(destination is ITopic) { return "Topic(" + destination.ToString() + ")"; } else { return "Queue(" + destination.ToString() + ")"; } } /// /// /// /// public static ActiveMQDestination Transform(IDestination destination) { ActiveMQDestination result = null; if(destination != null) { if(destination is ActiveMQDestination) { result = (ActiveMQDestination) destination; } else { if(destination is ITemporaryQueue) { result = new ActiveMQTempQueue(((IQueue) destination).QueueName); } else if(destination is ITemporaryTopic) { result = new ActiveMQTempTopic(((ITopic) destination).TopicName); } else if(destination is IQueue) { result = new ActiveMQQueue(((IQueue) destination).QueueName); } else if(destination is ITopic) { result = new ActiveMQTopic(((ITopic) destination).TopicName); } } } return result; } /// /// Create a Destination /// /// /// /// public static ActiveMQDestination CreateDestination(int type, String pyhsicalName) { ActiveMQDestination result = null; if(pyhsicalName == null) { return null; } else switch(type) { case ACTIVEMQ_TOPIC: result = new ActiveMQTopic(pyhsicalName); break; case ACTIVEMQ_TEMPORARY_TOPIC: result = new ActiveMQTempTopic(pyhsicalName); break; case ACTIVEMQ_QUEUE: result = new ActiveMQQueue(pyhsicalName); break; default: result = new ActiveMQTempQueue(pyhsicalName); break; } return result; } /// /// Create a temporary name from the clientId /// /// /// public static String CreateTemporaryName(String clientId) { return TEMP_PREFIX + clientId + TEMP_POSTFIX; } /// /// From a temporary destination find the clientId of the Connection that created it /// /// /// the clientId or null if not a temporary destination public static String GetClientId(ActiveMQDestination destination) { String answer = null; if(destination != null && destination.IsTemporary) { String name = destination.PhysicalName; int start = name.IndexOf(TEMP_PREFIX); if(start >= 0) { start += TEMP_PREFIX.Length; int stop = name.LastIndexOf(TEMP_POSTFIX); if(stop > start && stop < name.Length) { answer = name.Substring(start, stop); } } } return answer; } /// /// /// object to compare /// 1 if this is less than o else 0 if they are equal or -1 if this is less than o public int CompareTo(Object o) { if(o is ActiveMQDestination) { return CompareTo((ActiveMQDestination) o); } return -1; } /// /// Lets sort by name first then lets sort topics greater than queues /// /// another destination to compare against /// 1 if this is less than o else 0 if they are equal or -1 if this is less than o public int CompareTo(ActiveMQDestination that) { int answer = 0; if(physicalName != that.physicalName) { if(physicalName == null) { return -1; } else if(that.physicalName == null) { return 1; } answer = physicalName.CompareTo(that.physicalName); } if(answer == 0) { if(IsTopic) { if(that.IsQueue) { return 1; } } else { if(that.IsTopic) { return -1; } } } return answer; } /// /// /// Returns the Destination type public abstract int GetDestinationType(); public String PhysicalName { get { return this.physicalName; } set { this.physicalName = value; this.advisory = (value != null && value.StartsWith(ADVISORY_PREFIX)); } } /// /// Gets the Destination Type of this Destination as a String value which is one /// of {Queue,Topic,TempQueue,TempTopic}. /// /// /// The Destination Type as a String. /// public String GetDestinationTypeAsString() { switch(GetDestinationType()) { case ACTIVEMQ_QUEUE: return "Queue"; case ACTIVEMQ_TOPIC: return "Topic"; case ACTIVEMQ_TEMPORARY_QUEUE: return "TempQueue"; case ACTIVEMQ_TEMPORARY_TOPIC: return "TempTopic"; default: throw new NMSException("Invalid destination type: " + GetDestinationType()); } } /// /// Returns true if this destination represents a collection of /// destinations; allowing a set of destinations to be published to or subscribed /// from in one NMS operation. ///

/// If this destination is a composite then you can call {@link #getChildDestinations()} /// to return the list of child destinations. ///

public bool IsComposite { get { return physicalName.IndexOf(COMPOSITE_SEPARATOR) > 0; } } public ActiveMQDestination[] GetCompositeDestinations() { if (IsComposite) { LinkedList list = new LinkedList(); String[] composites = physicalName.Split(COMPOSITE_SEPARATOR.ToCharArray()); foreach(String composite in composites) { if (String.IsNullOrEmpty(composite.Trim())) { continue; } list.AddLast(composite.Trim()); } ActiveMQDestination[] compositeDestinations = new ActiveMQDestination[list.Count]; int counter = 0; foreach(String destination in list) { compositeDestinations[counter++] = CreateDestination(destination); } return compositeDestinations; } return new ActiveMQDestination[0]; } /// /// /// string representation of this instance public override String ToString() { switch(DestinationType) { case DestinationType.Topic: return "topic://" + PhysicalName; case DestinationType.TemporaryTopic: return "temp-topic://" + PhysicalName; case DestinationType.TemporaryQueue: return "temp-queue://" + PhysicalName; default: return "queue://" + PhysicalName; } } /// /// /// hashCode for this instance public override int GetHashCode() { int answer = 37; if(this.physicalName != null) { answer = physicalName.GetHashCode(); } if(IsTopic) { answer ^= 0xfabfab; } return answer; } /// /// if the object passed in is equivalent, return true /// /// the object to compare /// true if this instance and obj are equivalent public override bool Equals(Object obj) { bool result = this == obj; if(!result && obj != null && obj is ActiveMQDestination) { ActiveMQDestination other = (ActiveMQDestination) obj; result = this.GetDestinationType() == other.GetDestinationType() && this.physicalName.Equals(other.physicalName); } return result; } /// /// /// true if the destination matches multiple possible destinations public bool IsWildcard() { if(physicalName != null) { return physicalName.IndexOf(DestinationFilter.ANY_CHILD) >= 0 || physicalName.IndexOf(DestinationFilter.ANY_DESCENDENT) >= 0; } return false; } /// /// Factory method to create a child destination if this destination is a composite /// /// /// the created Destination public abstract ActiveMQDestination CreateDestination(String name); public abstract DestinationType DestinationType { get; } public override Object Clone() { // Since we are a derived class use the base's Clone() // to perform the shallow copy. Since it is shallow it // will include our derived class. Since we are derived, // this method is an override. ActiveMQDestination o = (ActiveMQDestination) base.Clone(); // Now do the deep work required // If any new variables are added then this routine will // likely need updating return o; } } }