Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/activemq/filter/DestinationMap.java


1   /**
2    * 
3    * Copyright 2004 Protique Ltd
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.activemq.filter;
19  
20  import java.util.HashSet;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  import org.activemq.message.ActiveMQDestination;
26  import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
27  
28  /**
29   * A Map-like data structure allowing values to be indexed by {@link ActiveMQDestination}
30   * and retrieved by destination - supporting both * and > style of wildcard
31   * as well as composite destinations.
32   * <br>
33   * This class assumes that the index changes rarely but that fast lookup into the index is required.
34   * So this class maintains a pre-calculated index for destination steps. So looking up the values
35   * for "TEST.*" or "*.TEST" will be pretty fast.
36   * <br>
37   * Looking up of a value could return a single value or a List of matching values if a wildcard or
38   * composite destination is used.
39   *
40   * @version $Revision: 1.1.1.1 $
41   */
42  public class DestinationMap {
43      private DestinationMapNode rootNode = new DestinationMapNode();
44      private Map vanillaDestinations = new ConcurrentHashMap();
45      private boolean containsWildCards = false;
46      protected static final String ANY_DESCENDENT = DestinationFilter.ANY_DESCENDENT;
47      protected static final String ANY_CHILD = DestinationFilter.ANY_CHILD;
48      private Set nullAnswer = new HashSet();
49  
50      /**
51       * Looks up the value(s) matching the given Destination key. For simple destinations
52       * this is typically a List of one single value, for wildcards or composite destinations this will typically be
53       * a List of matching values.
54       *
55       * @param key the destination to lookup
56       * @return a List of matching values or an empty list if there are no matching values.
57       */
58      public synchronized Set get(ActiveMQDestination key) {
59          if (key.isComposite()) {
60              List childDestinations = key.getChildDestinations();
61              Set answer = new HashSet(childDestinations.size());
62              for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
63                  ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
64                  Object value = get(childDestination);
65                  if (value instanceof Set) {
66                      answer.addAll((Set) value);
67                  }
68                  else if (value != null) {
69                      answer.add(value);
70                  }
71                  return answer;
72              }
73          }
74          return findWildcardMatches(key);
75      }
76  
77      /**
78       * add destination to the map
79       * @param key
80       * @param value
81       */
82      public synchronized void put(ActiveMQDestination key, Object value) {
83          if (key.isComposite()) {
84              List childDestinations = key.getChildDestinations();
85              for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
86                  ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
87                  put(childDestination, value);
88              }
89              return;
90          }
91          String[] paths = key.getDestinationPaths();
92          rootNode.add(paths, 0, value);
93          if (key.isWildcard()){
94              containsWildCards = true;
95          }
96          addToVanillaDestinations(key, value);
97      }
98  
99      /**
100      * Removes the value from the associated destination
101      * @param key
102      * @param value
103      */
104     public synchronized void remove(ActiveMQDestination key, Object value) {
105         if (key.isComposite()) {
106             List childDestinations = key.getChildDestinations();
107             for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
108                 ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
109                 remove(childDestination, value);
110             }
111             return;
112         }
113         String[] paths = key.getDestinationPaths();
114         rootNode.remove(paths, 0, value);
115         removeFromVanillaDestinations(key,value);
116         
117 
118     }
119 
120     // Implementation methods
121     //-------------------------------------------------------------------------
122     protected Set findWildcardMatches(ActiveMQDestination key) {
123         Set answer = nullAnswer;
124         if (!containsWildCards && !key.isWildcard()){
125             answer = getFromVanillaDestinations(key);
126         }else {
127             answer = new HashSet();
128             String[] paths = key.getDestinationPaths();
129             rootNode.appendMatchingValues(answer, paths, 0);
130         }
131         return answer;
132     }
133 
134     /**
135      * remove all destinations associated with a key
136      * @param key
137      */
138     public void removeAll(ActiveMQDestination key) {
139         if (key.isComposite()) {
140             List childDestinations = key.getChildDestinations();
141             for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
142                 ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
143                 removeAll(childDestination);
144             }
145             return;
146         }
147         String[] paths = key.getDestinationPaths();
148         rootNode.removeAll(paths, 0);
149         removeAllFromVanillaDestinations(key);
150     }
151     
152     synchronized private void addToVanillaDestinations(ActiveMQDestination key, Object value) {
153         Set set = new HashSet();
154         Set oldSet = (Set)vanillaDestinations.get(key);
155         if (oldSet != null) {
156             set.addAll(oldSet);
157         }
158         set.add(value);
159         vanillaDestinations.put(key,set);
160     }
161     
162     synchronized private void removeFromVanillaDestinations(ActiveMQDestination key,Object value){
163 
164         Set oldSet = (Set)vanillaDestinations.get(key);
165         if (oldSet != null) {
166             Set set = new HashSet(oldSet);
167             set.remove(value);
168             if (set.isEmpty()){
169                 vanillaDestinations.remove(key);
170             }
171             vanillaDestinations.put(key,set);
172         }
173         
174         validateContainsWildCards(key);
175     }
176     
177     private void removeAllFromVanillaDestinations(ActiveMQDestination key){
178         vanillaDestinations.remove(key);
179         validateContainsWildCards(key);
180     }
181     
182     private Set getFromVanillaDestinations(ActiveMQDestination key){
183         Set answer = (Set)vanillaDestinations.get(key);
184         return answer != null ? answer : nullAnswer;
185     }
186     
187     private void validateContainsWildCards(ActiveMQDestination key){
188         if (containsWildCards && key.isWildcard()){
189             containsWildCards = false;
190             for (Iterator i = vanillaDestinations.keySet().iterator(); i.hasNext();){
191                 ActiveMQDestination dest = (ActiveMQDestination)i.next();
192                 if (dest.isWildcard()){
193                     containsWildCards = true;
194                     break;
195                 }
196             }
197         }
198     }
199 
200 }