KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ubermq > jms > common > routing > impl > Router


1 package com.ubermq.jms.common.routing.impl;
2
3 import com.ubermq.jms.common.routing.*;
4
5 import java.util.*;
6 import java.io.*;
7
8 /**
9  * The core router implementation providing a route table. This implementation
10  * has memoization for faster route resolutions, a statistics interface,
11  * and supports dynamic route table modifications. <P>
12  *
13  * Possible enhancements include: keeping memoized routes if route table
14  * changes would not affect them, better statistics, and a way
15  * to serialize route table information to XML.<P>
16  *
17  * This implementation is not thread-safe. Guard all access of the
18  * router with appropriate synchronization.
19  *
20  */

21 public final class Router
22     implements IRouter, IConfigurableRouter
23 {
24     private final List excludedRoutes, routes;
25     private final Set nodes;
26     private String JavaDoc myLabel = "undefined";
27
28     // memoize our route table
29
private transient final Map memoization;
30     private transient volatile int nCacheHits, nCacheRequests;
31     private static final int MEMOIZATION_INITIAL_SIZE = 50;
32
33     // constants
34
public static final long serialVersionUID=15;
35
36     public Router()
37     {
38         this.excludedRoutes = new ArrayList();
39         this.routes = new ArrayList();
40         this.nodes = new HashSet();
41         this.memoization = new HashMap(MEMOIZATION_INITIAL_SIZE);
42     }
43
44     public Router(String JavaDoc label)
45     {
46         this();
47         setNodeLabel(label);
48     }
49
50     public void setNodeLabel(String JavaDoc label)
51     {
52         myLabel = label;
53     }
54
55     public String JavaDoc getNodeLabel()
56     {
57         return myLabel;
58     }
59
60     public void reset()
61     {
62         excludedRoutes.clear();
63         routes.clear();
64         nodes.clear();
65         resetCache();
66     }
67
68     private void resetCache()
69     {
70         memoization.clear();
71     }
72
73     public Collection getRoutes(SourceDescriptor source)
74     {
75         Object JavaDoc cached;
76         nCacheRequests++;
77
78         // look in the memoization for previous results if any
79
if ((cached = memoization.get(source)) != null)
80         {
81             // got a memoized set.
82
nCacheHits++;
83             return ((Collection)cached);
84         }
85         else
86         {
87             // no memoization, compute. this method will
88
// determine on the fly whether to cache for next time.
89
return reallyGetRoutes(source);
90         }
91     }
92
93     /**
94      * Returns a set of source specifications that are currently
95      * mapped to the specified destination node. This is considered a reverse
96      * lookup and may potentially be costly, depending on implementation.<P>
97      *
98      * @param dest the destination
99      * @return a Collection of SourceSpec objects
100      * @throws UnsupportedOperationException if the router does not
101      * choose to implement this reverse lookup function.
102      */

103     public Collection getRoutesTo(RouteDestNode dest)
104     {
105         Set toRemove = new HashSet();
106
107         for(Iterator i = routes.iterator();i.hasNext();)
108         {
109             BoundRoute br = (BoundRoute)i.next();
110             if (br.dest.equals(dest))
111                 toRemove.add(br.src);
112         }
113
114         return toRemove;
115     }
116
117     /**
118      * Does a reverse-lookup and returns a collection of
119      * <code>BoundRoute</code> objects that are the mappings
120      * such that <code>BoundRoute.dest.equals(dest)</code>.
121      *
122      * @return Collection of BoundRoute objects
123      * @param dest the destination
124      */

125     private Collection getBoundRoutesTo(RouteDestNode dest)
126     {
127         Set toRemove = new HashSet();
128
129         for(Iterator i = routes.iterator();i.hasNext();)
130         {
131             BoundRoute br = (BoundRoute)i.next();
132             if (br.dest.equals(dest))
133                 toRemove.add(br);
134         }
135
136         return toRemove;
137     }
138
139     private Set getExcludedSet(SourceDescriptor spec)
140     {
141         Set exclusionSet = new TreeSet();
142         // collect a list of nodes that we are excluded from.
143
for(Iterator i = excludedRoutes.iterator();i.hasNext();)
144         {
145             BoundRoute br = (BoundRoute)i.next();
146
147             if (br.src.matches(spec))
148             {
149                 exclusionSet.add(br.dest);
150             }
151         }
152
153         return exclusionSet;
154     }
155
156     public Set getKnownNodes()
157     {
158         return nodes;
159     }
160
161     private Collection reallyGetRoutes(SourceDescriptor spec)
162     {
163         Set exclusionSet, sendSet;
164
165         // if we are excluded from everywhere that we know about,
166
// shortcut and don't look at any more routes.
167
exclusionSet = getExcludedSet( spec );
168         if (exclusionSet.containsAll(nodes))
169             return Collections.EMPTY_SET;
170
171         // else, go through routes and find those that match.
172
//
173
Map preSendMap = new TreeMap();
174         boolean cacheable = true;
175         for(Iterator i = routes.iterator();i.hasNext();)
176         {
177             BoundRoute br = (BoundRoute)i.next();
178
179             if (br.src.matches(spec))
180             {
181                 Object JavaDoc existingSource = preSendMap.get(br.dest);
182                 if (existingSource == null ||
183                     br.src.isMoreSpecificThan(((BoundRoute)existingSource).src))
184                 {
185                     preSendMap.put(br.dest, br);
186                 }
187             }
188             
189             // can we cache results for this?
190
if (cacheable && !br.src.isIdempotentForEqualDescriptors())
191                 cacheable = false;
192         }
193
194         // take the dest's from the sendmap as sendSet
195
sendSet = new TreeSet();
196         for(Iterator i = preSendMap.values().iterator();i.hasNext();)
197         {
198             sendSet.add( ((BoundRoute)i.next()).getDestination() );
199         }
200
201         // well now we just take {routed - excluded} and give it back
202
// we will exclude any nodes that we do not know about.
203
sendSet.retainAll(nodes);
204         sendSet.removeAll(exclusionSet);
205         
206         // cache if we can
207
if (cacheable)
208             memoization.put(spec, sendSet);
209
210         return sendSet;
211     }
212
213     public void addRoute(SourceSpec spec, RouteDestNode rdn)
214     {
215         routes.remove( new BoundRoute(spec, rdn) );
216         routes.add( new BoundRoute(spec, rdn) );
217
218         resetCache();
219     }
220
221     public void excludeRoute(SourceSpec spec, RouteDestNode rdn)
222     {
223         excludedRoutes.add( new BoundRoute(spec, rdn) );
224         resetCache();
225     }
226
227     public void remove(SourceSpec spec, RouteDestNode rdn)
228     {
229         // remove this one from either routes and/or excluded routes
230
BoundRoute br = new BoundRoute(spec, rdn);
231         routes.remove(br);
232         resetCache();
233     }
234
235     public void removeExclusion(SourceSpec spec, RouteDestNode rdn)
236     {
237         // remove this one from either routes and/or excluded routes
238
BoundRoute br = new BoundRoute(spec, rdn);
239         excludedRoutes.remove(br);
240         resetCache();
241     }
242
243     public void removeRoutesTo(RouteDestNode node)
244     {
245         // remove routes
246
Collection toRemove = getBoundRoutesTo(node);
247         for(Iterator j = toRemove.iterator();j.hasNext();)
248             routes.remove(j.next());
249
250         // remove exclusions
251
toRemove.clear();
252         for(Iterator i = excludedRoutes.iterator();i.hasNext();)
253         {
254             BoundRoute br = (BoundRoute)i.next();
255             if (br.dest.equals(node))
256                 toRemove.add(br);
257         }
258         for(Iterator j = toRemove.iterator();j.hasNext();)
259             excludedRoutes.remove(j.next());
260     }
261
262     public void addKnownNode(RouteDestNode node)
263     {
264         nodes.add(node);
265         resetCache();
266     }
267
268     public void removeKnownNode(RouteDestNode node)
269     {
270         nodes.remove(node);
271         resetCache();
272     }
273
274     public String JavaDoc toString()
275     {
276         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
277         sb.append("Routes:\n");
278         for(Iterator i = routes.iterator();i.hasNext();)
279         {
280             BoundRoute br = (BoundRoute)i.next();
281
282             sb.append(br.toString()); sb.append("\n");
283         }
284
285         if (excludedRoutes.size() > 0) {
286             sb.append("\nExcluded Routes:\n");
287             for(Iterator i = excludedRoutes.iterator();i.hasNext();)
288             {
289                 BoundRoute br = (BoundRoute)i.next();
290                 sb.append(br.toString()); sb.append("\n");
291             }
292         }
293
294         sb.append("\nNodes: ");
295         for(Iterator i = nodes.iterator();i.hasNext();)
296         {
297             sb.append( ((RouteDestNode)i.next()).toString() ).append(" ");
298         }
299         sb.append("\n");
300
301         return sb.toString();
302     }
303
304     private static class BoundRoute
305     {
306         private SourceSpec src;
307         private RouteDestNode dest;
308
309         private BoundRoute(SourceSpec src, RouteDestNode rdn)
310         {
311             this.src = src;
312             this.dest = rdn;
313         }
314
315         public BoundRoute()
316         {
317         }
318
319         public RouteDestNode getDestination() {return dest;}
320
321         public String JavaDoc toString()
322         {
323             return src.getDisplayName() + " -> " + dest.toString();
324         }
325
326         public boolean equals(Object JavaDoc obj)
327         {
328             try {
329                 BoundRoute br = (BoundRoute)obj;
330                 return (br.src.equals(src) &&
331                             br.dest.equals(dest));
332             } catch(ClassCastException JavaDoc cce) {
333                 return false;
334             }
335         }
336     }
337 }
338
Popular Tags