KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgroups > stack > Configurator


1 // $Id: Configurator.java,v 1.10 2005/04/23 12:44:06 belaban Exp $
2

3 package org.jgroups.stack;
4
5
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.jgroups.Event;
9
10 import java.util.Properties JavaDoc;
11 import java.util.StringTokenizer JavaDoc;
12 import java.util.Vector JavaDoc;
13
14
15 /**
16  * The task if this class is to setup and configure the protocol stack. A string describing
17  * the desired setup, which is both the layering and the configuration of each layer, is
18  * given to the configurator which creates and configures the protocol stack and returns
19  * a reference to the top layer (Protocol).<p>
20  * Future functionality will include the capability to dynamically modify the layering
21  * of the protocol stack and the properties of each layer.
22  * @author Bela Ban
23  */

24 public class Configurator {
25
26      protected final Log log=LogFactory.getLog(getClass());
27
28
29     /**
30      * The configuration string has a number of entries, separated by a ':' (colon).
31      * Each entry consists of the name of the protocol, followed by an optional configuration
32      * of that protocol. The configuration is enclosed in parentheses, and contains entries
33      * which are name/value pairs connected with an assignment sign (=) and separated by
34      * a semicolon.
35      * <pre>UDP(in_port=5555;out_port=4445):FRAG(frag_size=1024)</pre><p>
36      * The <em>first</em> entry defines the <em>bottommost</em> layer, the string is parsed
37      * left to right and the protocol stack constructed bottom up. Example: the string
38      * "UDP(in_port=5555):FRAG(frag_size=32000):DEBUG" results is the following stack:<pre>
39      *
40      * -----------------------
41      * | DEBUG |
42      * |-----------------------|
43      * | FRAG frag_size=32000 |
44      * |-----------------------|
45      * | UDP in_port=32000 |
46      * -----------------------
47      * </pre>
48      */

49     public Protocol setupProtocolStack(String JavaDoc configuration, ProtocolStack st) throws Exception JavaDoc {
50         Protocol protocol_stack=null;
51         Vector JavaDoc protocol_configs;
52         Vector JavaDoc protocols;
53
54         protocol_configs=parseConfigurations(configuration);
55         protocols=createProtocols(protocol_configs, st);
56         if(protocols == null)
57             return null;
58         protocol_stack=connectProtocols(protocols);
59         return protocol_stack;
60     }
61
62
63     public void startProtocolStack(Protocol bottom_prot) {
64         while(bottom_prot != null) {
65             bottom_prot.startDownHandler();
66             bottom_prot.startUpHandler();
67             bottom_prot=bottom_prot.getUpProtocol();
68         }
69     }
70
71
72     public void stopProtocolStack(Protocol start_prot) {
73         while(start_prot != null) {
74             start_prot.stopInternal();
75             start_prot.destroy();
76             start_prot=start_prot.getDownProtocol();
77         }
78     }
79
80
81     public Protocol findProtocol(Protocol prot_stack, String JavaDoc name) {
82         String JavaDoc s;
83         Protocol curr_prot=prot_stack;
84
85         while(true) {
86             s=curr_prot.getName();
87             if(s == null)
88                 continue;
89             if(s.equals(name))
90                 return curr_prot;
91             curr_prot=curr_prot.getDownProtocol();
92             if(curr_prot == null)
93                 break;
94         }
95         return null;
96     }
97
98
99     public Protocol getBottommostProtocol(Protocol prot_stack) {
100         Protocol tmp=null, curr_prot=prot_stack;
101
102         while(true) {
103             if((tmp=curr_prot.getDownProtocol()) == null)
104                 break;
105             curr_prot=tmp;
106         }
107         return curr_prot;
108     }
109
110
111     /**
112      * Creates a new protocol given the protocol specification. Initializes the properties and starts the
113      * up and down handler threads.
114      * @param prot_spec The specification of the protocol. Same convention as for specifying a protocol stack.
115      * An exception will be thrown if the class cannot be created. Example:
116      * <pre>"VERIFY_SUSPECT(timeout=1500)"</pre> Note that no colons (:) have to be
117      * specified
118      * @param stack The protocol stack
119      * @return Protocol The newly created protocol
120      * @exception Exception Will be thrown when the new protocol cannot be created
121      */

122     public Protocol createProtocol(String JavaDoc prot_spec, ProtocolStack stack) throws Exception JavaDoc {
123         ProtocolConfiguration config;
124         Protocol prot;
125
126         if(prot_spec == null) throw new Exception JavaDoc("Configurator.createProtocol(): prot_spec is null");
127
128         // parse the configuration for this protocol
129
config=new ProtocolConfiguration(prot_spec);
130
131         // create an instance of the protocol class and configure it
132
prot=config.createLayer(stack);
133
134         // start the handler threads (unless down_thread or up_thread are set to false)
135
prot.startDownHandler();
136         prot.startUpHandler();
137
138         return prot;
139     }
140
141
142     /**
143      * Inserts an already created (and initialized) protocol into the protocol list. Sets the links
144      * to the protocols above and below correctly and adjusts the linked list of protocols accordingly.
145      * @param prot The protocol to be inserted. Before insertion, a sanity check will ensure that none
146      * of the existing protocols have the same name as the new protocol.
147      * @param position Where to place the protocol with respect to the neighbor_prot (ABOVE, BELOW)
148      * @param neighbor_prot The name of the neighbor protocol. An exception will be thrown if this name
149      * is not found
150      * @param stack The protocol stack
151      * @exception Exception Will be thrown when the new protocol cannot be created, or inserted.
152      */

153     public void insertProtocol(Protocol prot, int position, String JavaDoc neighbor_prot, ProtocolStack stack) throws Exception JavaDoc {
154         if(neighbor_prot == null) throw new Exception JavaDoc("Configurator.insertProtocol(): neighbor_prot is null");
155         if(position != ProtocolStack.ABOVE && position != ProtocolStack.BELOW)
156             throw new Exception JavaDoc("Configurator.insertProtocol(): position has to be ABOVE or BELOW");
157
158
159         // find the neighbors below and above
160

161
162
163         // connect to the protocol layer below and above
164

165
166     }
167
168
169     /**
170      * Removes a protocol from the stack. Stops the protocol and readjusts the linked lists of
171      * protocols.
172      * @param prot_name The name of the protocol. Since all protocol names in a stack have to be unique
173      * (otherwise the stack won't be created), the name refers to just 1 protocol.
174      * @exception Exception Thrown if the protocol cannot be stopped correctly.
175      */

176     public void removeProtocol(String JavaDoc prot_name) throws Exception JavaDoc {
177     }
178
179
180
181     /* ------------------------------- Private Methods ------------------------------------- */
182
183
184     /**
185      * Creates a protocol stack by iterating through the protocol list and connecting
186      * adjacent layers. The list starts with the topmost layer and has the bottommost
187      * layer at the tail. When all layers are connected the algorithms traverses the list
188      * once more to call startInternal() on each layer.
189      * @param protocol_list List of Protocol elements (from top to bottom)
190      * @return Protocol stack
191      */

192     private Protocol connectProtocols(Vector JavaDoc protocol_list) {
193         Protocol current_layer=null, next_layer=null;
194
195         for(int i=0; i < protocol_list.size(); i++) {
196             current_layer=(Protocol)protocol_list.elementAt(i);
197             if(i + 1 >= protocol_list.size())
198                 break;
199             next_layer=(Protocol)protocol_list.elementAt(i + 1);
200             current_layer.setUpProtocol(next_layer);
201             next_layer.setDownProtocol(current_layer);
202         }
203         return current_layer;
204     }
205
206
207     /**
208      * Get a string of the form "P1(config_str1):P2:P3(config_str3)" and return
209      * ProtocolConfigurations for it. That means, parse "P1(config_str1)", "P2" and
210      * "P3(config_str3)"
211      * @param config_str Configuration string
212      * @return Vector of ProtocolConfigurations
213      */

214     public Vector JavaDoc parseComponentStrings(String JavaDoc config_str, String JavaDoc delimiter) {
215         Vector JavaDoc retval=new Vector JavaDoc();
216         StringTokenizer JavaDoc tok;
217         String JavaDoc token;
218
219         /*tok=new StringTokenizer(config_str, delimiter, false);
220         while(tok.hasMoreTokens()) {
221             token=tok.nextToken();
222             retval.addElement(token);
223         }*/

224         // change suggested by gwoolsey
225
tok=new StringTokenizer JavaDoc(config_str, delimiter, false);
226         while(tok.hasMoreTokens()) {
227             token=tok.nextToken();
228             while(token.endsWith("\\"))
229                 token=token.substring(0, token.length() - 1) + delimiter + tok.nextToken();
230             retval.addElement(token);
231         }
232
233         return retval;
234     }
235
236
237     /**
238      * Return a number of ProtocolConfigurations in a vector
239      * @param configuration protocol-stack configuration string
240      * @return Vector of ProtocolConfigurations
241      */

242     public Vector JavaDoc parseConfigurations(String JavaDoc configuration) throws Exception JavaDoc {
243         Vector JavaDoc retval=new Vector JavaDoc();
244         Vector JavaDoc component_strings=parseComponentStrings(configuration, ":");
245         String JavaDoc component_string;
246         ProtocolConfiguration protocol_config;
247
248         if(component_strings == null)
249             return null;
250         for(int i=0; i < component_strings.size(); i++) {
251             component_string=(String JavaDoc)component_strings.elementAt(i);
252             protocol_config=new ProtocolConfiguration(component_string);
253             retval.addElement(protocol_config);
254         }
255         return retval;
256     }
257
258
259     /**
260      * Takes vector of ProtocolConfigurations, iterates through it, creates Protocol for
261      * each ProtocolConfiguration and returns all Protocols in a vector.
262      * @param protocol_configs Vector of ProtocolConfigurations
263      * @param stack The protocol stack
264      * @return Vector of Protocols
265      */

266     private Vector JavaDoc createProtocols(Vector JavaDoc protocol_configs, ProtocolStack stack) throws Exception JavaDoc {
267         Vector JavaDoc retval=new Vector JavaDoc();
268         ProtocolConfiguration protocol_config;
269         Protocol layer;
270
271         for(int i=0; i < protocol_configs.size(); i++) {
272             protocol_config=(ProtocolConfiguration)protocol_configs.elementAt(i);
273             layer=protocol_config.createLayer(stack);
274             if(layer == null)
275                 return null;
276             retval.addElement(layer);
277         }
278
279         sanityCheck(retval);
280         return retval;
281     }
282
283
284     /**
285      Throws an exception if sanity check fails. Possible sanity check is uniqueness of all protocol
286      names.
287      */

288     public void sanityCheck(Vector JavaDoc protocols) throws Exception JavaDoc {
289         Vector JavaDoc names=new Vector JavaDoc();
290         Protocol prot;
291         String JavaDoc name;
292         ProtocolReq req;
293         Vector JavaDoc req_list=new Vector JavaDoc();
294         int evt_type;
295
296         // Checks for unique names
297
for(int i=0; i < protocols.size(); i++) {
298             prot=(Protocol)protocols.elementAt(i);
299             name=prot.getName();
300             for(int j=0; j < names.size(); j++) {
301                 if(name.equals(names.elementAt(j))) {
302                     throw new Exception JavaDoc("Configurator.sanityCheck(): protocol name " + name +
303                                         " has been used more than once; protocol names have to be unique !");
304                 }
305             }
306             names.addElement(name);
307         }
308
309
310         // Checks whether all requirements of all layers are met
311
for(int i=0; i < protocols.size(); i++) {
312             prot=(Protocol)protocols.elementAt(i);
313             req=new ProtocolReq(prot.getName());
314             req.up_reqs=prot.requiredUpServices();
315             req.down_reqs=prot.requiredDownServices();
316             req.up_provides=prot.providedUpServices();
317             req.down_provides=prot.providedDownServices();
318             req_list.addElement(req);
319         }
320
321
322         for(int i=0; i < req_list.size(); i++) {
323             req=(ProtocolReq)req_list.elementAt(i);
324
325             // check whether layers above this one provide corresponding down services
326
if(req.up_reqs != null) {
327                 for(int j=0; j < req.up_reqs.size(); j++) {
328                     evt_type=((Integer JavaDoc)req.up_reqs.elementAt(j)).intValue();
329
330                     if(!providesDownServices(i, req_list, evt_type)) {
331                         throw new Exception JavaDoc("Configurator.sanityCheck(): event " +
332                                             Event.type2String(evt_type) + " is required by " +
333                                             req.name + ", but not provided by any of the layers above");
334                     }
335                 }
336             }
337
338             // check whether layers below this one provide corresponding up services
339
if(req.down_reqs != null) { // check whether layers above this one provide up_reqs
340
for(int j=0; j < req.down_reqs.size(); j++) {
341                     evt_type=((Integer JavaDoc)req.down_reqs.elementAt(j)).intValue();
342
343                     if(!providesUpServices(i, req_list, evt_type)) {
344                         throw new Exception JavaDoc("Configurator.sanityCheck(): event " +
345                                             Event.type2String(evt_type) + " is required by " +
346                                             req.name + ", but not provided by any of the layers below");
347                     }
348                 }
349             }
350
351         }
352     }
353
354
355     /** Check whether any of the protocols 'below' end_index provide evt_type */
356     boolean providesUpServices(int end_index, Vector JavaDoc req_list, int evt_type) {
357         ProtocolReq req;
358
359         for(int i=0; i < end_index; i++) {
360             req=(ProtocolReq)req_list.elementAt(i);
361             if(req.providesUpService(evt_type))
362                 return true;
363         }
364         return false;
365     }
366
367
368     /** Checks whether any of the protocols 'above' start_index provide evt_type */
369     boolean providesDownServices(int start_index, Vector JavaDoc req_list, int evt_type) {
370         ProtocolReq req;
371
372         for(int i=start_index; i < req_list.size(); i++) {
373             req=(ProtocolReq)req_list.elementAt(i);
374             if(req.providesDownService(evt_type))
375                 return true;
376         }
377         return false;
378     }
379
380
381
382     /* --------------------------- End of Private Methods ---------------------------------- */
383
384
385
386
387
388     private static class ProtocolReq {
389         Vector JavaDoc up_reqs=null;
390         Vector JavaDoc down_reqs=null;
391         Vector JavaDoc up_provides=null;
392         Vector JavaDoc down_provides=null;
393         String JavaDoc name=null;
394
395         ProtocolReq(String JavaDoc name) {
396             this.name=name;
397         }
398
399
400         boolean providesUpService(int evt_type) {
401             int type;
402
403             if(up_provides != null) {
404                 for(int i=0; i < up_provides.size(); i++) {
405                     type=((Integer JavaDoc)up_provides.elementAt(i)).intValue();
406                     if(type == evt_type)
407                         return true;
408                 }
409             }
410             return false;
411         }
412
413         boolean providesDownService(int evt_type) {
414             int type;
415
416             if(down_provides != null) {
417                 for(int i=0; i < down_provides.size(); i++) {
418                     type=((Integer JavaDoc)down_provides.elementAt(i)).intValue();
419                     if(type == evt_type)
420                         return true;
421                 }
422             }
423             return false;
424         }
425
426
427         public String JavaDoc toString() {
428             StringBuffer JavaDoc ret=new StringBuffer JavaDoc();
429             ret.append('\n' + name + ':');
430             if(up_reqs != null)
431                 ret.append("\nRequires from above: " + printUpReqs());
432
433             if(down_reqs != null)
434                 ret.append("\nRequires from below: " + printDownReqs());
435
436             if(up_provides != null)
437                 ret.append("\nProvides to above: " + printUpProvides());
438
439             if(down_provides != null)
440                 ret.append("\nProvides to below: " + printDownProvides());
441             return ret.toString();
442         }
443
444
445         String JavaDoc printUpReqs() {
446             StringBuffer JavaDoc ret=new StringBuffer JavaDoc("[");
447             if(up_reqs != null) {
448                 for(int i=0; i < up_reqs.size(); i++) {
449                     ret.append(Event.type2String(((Integer JavaDoc)up_reqs.elementAt(i)).intValue()) + ' ');
450                 }
451             }
452             return ret.toString() + ']';
453         }
454
455         String JavaDoc printDownReqs() {
456             StringBuffer JavaDoc ret=new StringBuffer JavaDoc("[");
457             if(down_reqs != null) {
458                 for(int i=0; i < down_reqs.size(); i++) {
459                     ret.append(Event.type2String(((Integer JavaDoc)down_reqs.elementAt(i)).intValue()) + ' ');
460                 }
461             }
462             return ret.toString() + ']';
463         }
464
465
466         String JavaDoc printUpProvides() {
467             StringBuffer JavaDoc ret=new StringBuffer JavaDoc("[");
468             if(up_provides != null) {
469                 for(int i=0; i < up_provides.size(); i++) {
470                     ret.append(Event.type2String(((Integer JavaDoc)up_provides.elementAt(i)).intValue()) + ' ');
471                 }
472             }
473             return ret.toString() + ']';
474         }
475
476         String JavaDoc printDownProvides() {
477             StringBuffer JavaDoc ret=new StringBuffer JavaDoc("[");
478             if(down_provides != null) {
479                 for(int i=0; i < down_provides.size(); i++)
480                     ret.append(Event.type2String(((Integer JavaDoc)down_provides.elementAt(i)).intValue()) +
481                                ' ');
482             }
483             return ret.toString() + ']';
484         }
485
486     }
487
488
489     /**
490      * Parses and encapsulates the specification for 1 protocol of the protocol stack, e.g.
491      * <code>UNICAST(timeout=5000)</code>
492      */

493     public class ProtocolConfiguration {
494         private String JavaDoc protocol_name=null;
495         private String JavaDoc properties_str=null;
496         private final Properties JavaDoc properties=new Properties JavaDoc();
497         private static final String JavaDoc protocol_prefix="org.jgroups.protocols";
498
499
500         /**
501          * Creates a new ProtocolConfiguration.
502          * @param config_str The configuration specification for the protocol, e.g.
503          * <pre>VERIFY_SUSPECT(timeout=1500)</pre>
504          */

505         public ProtocolConfiguration(String JavaDoc config_str) throws Exception JavaDoc {
506             setContents(config_str);
507         }
508
509         public String JavaDoc getProtocolName() {
510             return protocol_name;
511         }
512
513         public Properties JavaDoc getProperties() {
514             return properties;
515         }
516
517
518         void setContents(String JavaDoc config_str) throws Exception JavaDoc {
519             int index=config_str.indexOf('('); // e.g. "UDP(in_port=3333)"
520
int end_index=config_str.lastIndexOf(')');
521
522             if(index == -1) {
523                 protocol_name=config_str;
524             }
525             else {
526                 if(end_index == -1) {
527                     throw new Exception JavaDoc("Configurator.ProtocolConfiguration.setContents(): closing ')' " +
528                                         "not found in " + config_str + ": properties cannot be set !");
529                 }
530                 else {
531                     properties_str=config_str.substring(index + 1, end_index);
532                     protocol_name=config_str.substring(0, index);
533                 }
534             }
535
536             /* "in_port=5555;out_port=6666" */
537             if(properties_str != null) {
538                 Vector JavaDoc components=parseComponentStrings(properties_str, ";");
539                 if(components.size() > 0) {
540                     for(int i=0; i < components.size(); i++) {
541                         String JavaDoc name, value, comp=(String JavaDoc)components.elementAt(i);
542                         index=comp.indexOf('=');
543                         if(index == -1) {
544                             throw new Exception JavaDoc("Configurator.ProtocolConfiguration.setContents(): " +
545                                                 "'=' not found in " + comp);
546                         }
547                         name=comp.substring(0, index);
548                         value=comp.substring(index + 1, comp.length());
549                         properties.put(name, value);
550                     }
551                 }
552             }
553         }
554
555
556         Protocol createLayer(ProtocolStack prot_stack) throws Exception JavaDoc {
557             Protocol retval=null;
558             if(protocol_name == null)
559                 return null;
560
561             // SL: we use the context classloader to be able to work correctly in
562
// complex classloaders environments
563
// FH: The context class loader doesn't work in Tomcat
564
ClassLoader JavaDoc loader=Thread.currentThread().getContextClassLoader();
565             // When invoked from C++ getContextClassLoader returns null
566
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4489399
567
//so:
568
if(loader == null){
569                 loader = ClassLoader.getSystemClassLoader();
570             }
571             try {
572                 String JavaDoc defaultProtocolName=protocol_prefix + '.' + protocol_name;
573                 Class JavaDoc clazz=null;
574
575                 // first try to load the class in the default package
576
//
577
try {
578                     clazz=loader.loadClass(defaultProtocolName);
579                 }
580                 catch(ClassNotFoundException JavaDoc cnfe) {
581                     //try using another class loader
582
try {
583                         // loader=this.getClass().getClassLoader();
584
loader=Thread.currentThread().getContextClassLoader();
585                         clazz=loader.loadClass(defaultProtocolName);
586                     }
587                     catch(Exception JavaDoc ignore) {
588                     }
589                     // unable to find it in the default package... guess
590
// it is an absolute package name
591
// try two class loaders, first the same one that
592
// loaded this class, then try the
593
try {
594                         // loader=this.getClass().getClassLoader();
595
loader=Thread.currentThread().getContextClassLoader();
596                         if(clazz == null) clazz=loader.loadClass(protocol_name);
597                     }
598                     catch(Exception JavaDoc ignore) {
599                     }
600                     //
601
try {
602                         loader=Thread.currentThread().getContextClassLoader();
603                         if(clazz == null) clazz=loader.loadClass(protocol_name);
604                     }
605                     catch(ClassNotFoundException JavaDoc cnfe2) {
606                         throw new Exception JavaDoc("Configurator.ProtocolConfiguration.createLayer(): " +
607                                             "unable to load class for protocol " + protocol_name +
608                                             " (either as an absolute - " + protocol_name +
609                                             " - or relative - " + defaultProtocolName +
610                                             " - package name)!");
611                     }
612                 }
613
614                 retval=(Protocol)clazz.newInstance();
615
616                 if(retval == null)
617                     throw new Exception JavaDoc("Configurator.ProtocolConfiguration.createLayer(): " +
618                                         "creation of instance for protocol " + protocol_name + "failed !");
619                 retval.setProtocolStack(prot_stack);
620                 if(properties != null)
621                     if(!retval.setPropertiesInternal(properties))
622                         return null;
623                 retval.init();
624             }
625             catch(InstantiationException JavaDoc inst_ex) {
626                 log.error("an instance of " + protocol_name + " could not be created. Please check that it implements" +
627                         " interface Protocol and that is has a public empty constructor !");
628                 throw inst_ex;
629             }
630             return retval;
631         }
632
633
634         public String JavaDoc toString() {
635             StringBuffer JavaDoc retval=new StringBuffer JavaDoc();
636             retval.append("Protocol: ");
637             if(protocol_name == null)
638                 retval.append("<unknown>");
639             else
640                 retval.append(protocol_name);
641             if(properties != null)
642                 retval.append("(" + properties + ')');
643             return retval.toString();
644         }
645     }
646
647
648     public static void main(String JavaDoc args[]) {
649         if(args.length != 1) {
650             System.err.println("Configurator <string>");
651             System.exit(0);
652         }
653         String JavaDoc config_str=args[0];
654         Configurator conf=new Configurator();
655         Vector JavaDoc protocol_configs;
656         Vector JavaDoc protocols=null;
657         Protocol protocol_stack;
658
659
660         try {
661             protocol_configs=conf.parseConfigurations(config_str);
662             protocols=conf.createProtocols(protocol_configs, null);
663             if(protocols == null)
664                 return;
665             protocol_stack=conf.connectProtocols(protocols);
666             Thread.sleep(3000);
667             conf.stopProtocolStack(protocol_stack);
668             // conf.stopProtocolStackInternal(protocol_stack);
669
}
670         catch(Exception JavaDoc e) {
671             System.err.println(e);
672         }
673
674         System.err.println(protocols);
675     }
676
677
678 }
679
680
681
Popular Tags