KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > core > dist > Topology


1 /*
2   Copyright (C) 2001 Renaud Pawlak <renaud@aopsys.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

17
18 package org.objectweb.jac.core.dist;
19
20 import gnu.regexp.*;
21 import java.io.Serializable JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Vector JavaDoc;
27 import org.apache.log4j.Level;
28 import org.apache.log4j.Logger;
29 import org.objectweb.jac.core.ACConfiguration;
30 import org.objectweb.jac.core.ACManager;
31 import org.objectweb.jac.core.Application;
32 import org.objectweb.jac.core.ApplicationRepository;
33 import org.objectweb.jac.core.NameRepository;
34 import org.objectweb.jac.core.Wrappee;
35 import org.objectweb.jac.core.Wrapping;
36 import org.objectweb.jac.util.ExtArrays;
37
38 /**
39  * This class defines a generic topology where nodes are a
40  * set of reachable containers.
41  *
42  * <p>It is used by the distribution aspect to define distribution,
43  * deployment, and replication schemes.<p>
44  *
45  * @see org.objectweb.jac.core.dist.RemoteContainer */

46
47 public class Topology implements Serializable JavaDoc {
48     static Logger logger = Logger.getLogger("topology");
49     static Logger loggerDist = Logger.getLogger("dist");
50     static Logger loggerApp = Logger.getLogger("application");
51     static Logger loggerAspects = Logger.getLogger("aspects");
52
53     public boolean bootstrapFlag = false;
54
55     /** The name of the property that defines the initial global
56         topology in the org.objectweb.jac.prop file. */

57     //protected static String topologyProp = "org.objectweb.jac.topology";
58

59     /** Store the gobal topology of the JAC distributed system. */
60     protected static Topology globalTopology = null;
61
62     static Hashtable JavaDoc applicationsTopologies = new Hashtable JavaDoc();
63
64     /**
65      * Returns the topology defined for the given application.
66      *
67      * @param application the application
68      * @return the corresponding topology
69      */

70     public static Topology getTopology(Application application) {
71         if( application == null ) return null;
72         return (Topology)applicationsTopologies.get(application);
73     }
74
75     /**
76      * Sets the topology for a given application.
77      *
78      * @param application the application
79      * @param topology the corresponding topology
80      */

81     public static void setTopology(Application application,
82                                    Topology topology) {
83         if(application == null || topology == null) return;
84         loggerApp.debug("setting "+topology+" to "+application);
85         applicationsTopologies.put(application,topology);
86     }
87
88     /**
89      * This method returns the gobal topology of the JAC distributed
90      * middleware.<p>
91      *
92      * This instance of topology is set in strong consistency so that
93      * all the container of the distributed name/aspect space are
94      * notified when a container is added or removed.<p>
95      *
96      * @return the global topology
97      */

98     public static Topology get() {
99         if (globalTopology == null) {
100
101             // creates the global topology
102
new Topology();
103         }
104         return globalTopology;
105     }
106
107     /**
108      * Resets the global topology by re-resolving the different
109      * containers.
110      */

111     public static void reset() {
112         globalTopology=null;
113         get();
114     }
115
116     /**
117      * This method returns a topology with all the containers that
118      * match the regular expression within the global topology of org.objectweb.jac.
119      *
120      * @param regexp a regular expression on the container names
121      * @return a partial topology
122      * @see #getPartialTopology(String)
123      */

124     public static Topology getPartialTopology(RE regexp) {
125         return new Topology(get().getContainers(regexp));
126     }
127
128     /**
129      * This method returns the first container that matches the host
130      * expression.
131      */

132     public RemoteContainer getFirstContainer(String JavaDoc sregexp) {
133         RE regexp = null;
134         try {
135             regexp = new RE(sregexp);
136         } catch(Exception JavaDoc e) {
137             return null;
138         }
139         for (int i=0; i<containers.size(); i++) {
140             if (regexp.isMatch(((RemoteContainer)containers.get(i)).getName())) {
141                 return (RemoteContainer)containers.get(i);
142             }
143         }
144         return null;
145     }
146
147     /**
148      * This method returns a topology with all the containers that
149      * match the regular expression within the global topology of org.objectweb.jac.
150      *
151      * @param regexp a regular expression (as a string) on the
152      * container names
153      * @return a partial topology
154      */

155     public static Topology getPartialTopology(String JavaDoc regexp) {
156         if (globalTopology == null)
157             return null;
158         RE re = null;
159         try {
160             re = new RE(regexp);
161         } catch(Exception JavaDoc e) {
162             logger.error("getPartialTopology "+regexp,e);
163             return null;
164         }
165         //Log.trace("topology","get partial topology "+regexp+"(global topology="+globalTopology);
166
RemoteContainer[] containers = globalTopology.getContainers(re);
167         logger.debug("get partial topology found "+Arrays.asList(containers));
168         return new Topology(containers);
169     }
170
171     /** Store the containers of the topology. */
172     public List JavaDoc containers = new Vector JavaDoc();
173
174     /** Store the remote references on the name repository for
175         optimization matter. */

176     public List JavaDoc nameReps = new Vector JavaDoc();
177
178     /**
179      * This constructor builds a topology and set it to global if a
180      * global topology does not exist yet.
181      *
182      * @see Topology#get()
183      */

184     public Topology() {
185         logger.debug("Creating Topology...");
186         if (globalTopology == null) {
187             NameRepository.get().register("JAC_topology", this);
188             globalTopology = this;
189         }
190         createNameReps();
191         logger.debug("Topology created");
192     }
193
194     /**
195      * Builds a topology with the given container identifiers. The
196      * identifier is protocol dependent.<p>
197      *
198      * This method transforms the names into remote containers
199      * references by calling <code>resolve</code>.
200      *
201      * @param someNames a set of container names
202      * @see org.objectweb.jac.core.dist.RemoteContainer#resolve(String)
203      */

204     public Topology(String JavaDoc[] someNames) {
205         for(int i=0; i<someNames.length; i++) {
206             containers.add(RemoteContainer.resolve(someNames[i]));
207         }
208         createNameReps();
209     }
210
211     /**
212      * Creates the remote references on the name repositories.<p>
213      *
214      * This method is used for optimization reasons. Indeed, it allows
215      * the topology to avoid the dynamic resolution of the containers
216      * when accessing them.<p>
217      *
218      * @see #getContainers()
219      * @see #getContainer(int)
220      * @see #getDistContainers()
221      */

222     public void createNameReps() {
223         nameReps.clear();
224         for (int i=0; i<containers.size(); i++) {
225             RemoteContainer cc = (RemoteContainer) containers.get(i);
226             RemoteRef rr = null;
227             if (!cc.isLocal()) {
228                 rr = cc.bindTo ("JAC_name_repository");
229             } else {
230                 rr = RemoteRef.create("JAC_name_repository",
231                                       (Wrappee)NameRepository.get());
232             }
233             nameReps.add(rr);
234         }
235     }
236
237     /**
238      * Builds a topology from a set of containers.
239      *
240      * @param someContainers the container of the new topology
241      *
242      * @see #getContainers()
243      * @see #getContainer(int)
244      * @see #getDistContainers()
245      */

246     public Topology(RemoteContainer[] someContainers) {
247         containers.addAll(Arrays.asList(someContainers));
248     }
249
250     /**
251      * Returns all the containers of the topology.<p>
252      *
253      * @return an array of containers
254      *
255      * @see #getContainer(int)
256      * @see #getDistContainers()
257      */

258     public RemoteContainer[] getContainers() {
259         RemoteContainer[] res = new RemoteContainer[containers.size()];
260         System.arraycopy(containers.toArray(), 0, res, 0, res.length);
261         return res;
262     }
263
264     /**
265      * Returns a given container.<p>
266      *
267      * @param index a valid index
268      * @return the container that corresponds to the index
269      *
270      * @see #getContainers()
271      * @see #getDistContainers()
272      */

273     public RemoteContainer getContainer(int index) {
274         return (RemoteContainer)containers.get(index);
275     }
276
277     /**
278      * Returns the container of the topology minus the local one if
279      * any.<p>
280      *
281      * This method is typically used to deploy objects on a topology
282      * (when you do not want the object to be also depoyed on the local
283      * container).<p>
284      *
285      * @return an array of containers
286      *
287      * @see org.objectweb.jac.core.dist.RemoteContainer#isLocal()
288      * @see #getContainers()
289      * @see #getContainer(int)
290      */

291     public RemoteContainer[] getDistContainers() {
292         Vector JavaDoc ret = new Vector JavaDoc();
293         for ( int i=0; i<containers.size(); i++) {
294             RemoteContainer cc = (RemoteContainer)containers.get(i);
295             if (!cc.isLocal()) {
296                 ret.add (cc);
297             }
298         }
299         RemoteContainer[] rcs = new RemoteContainer[ret.size()];
300         System.arraycopy(ret.toArray(), 0, rcs, 0, ret.size());
301         return rcs;
302     }
303
304     /**
305      * Tells if the current topology contains the local container.
306      *
307      * @return true if the local container is included in the topology
308      */

309     public boolean containsLocal() {
310         for (int i=0; i<containers.size(); i++) {
311             RemoteContainer cc = (RemoteContainer)containers.get(i);
312             if (cc.isLocal()) {
313                 return true;
314             }
315         }
316         return false;
317     }
318    
319     /**
320      * Gets a set of remote references on all the remote replicas of a
321      * local object for the current topology.
322      *
323      * @param localObject the local object of which the replicas are
324      * seeked
325      * @return the replicas references
326      */

327     public Vector JavaDoc getReplicas(Wrappee localObject) {
328         String JavaDoc name = NameRepository.get().getName( localObject );
329         Vector JavaDoc vRes = new Vector JavaDoc();
330         for ( int i = 0; i < countContainers(); i++ ) {
331             logger.debug("try to find "+name+" on "+getContainer(i)+
332                       " -- local container is: "+Distd.getLocalContainerName());
333             RemoteRef rr=null;
334             if(!getContainer(i).getName().equals(Distd.getLocalContainerName())) {
335                 rr=getContainer(i).bindTo(name);
336             }
337             if( rr != null ) {
338                 vRes.add( rr );
339             } else {
340                 logger.debug("remote object not found!");
341             }
342         }
343         return vRes;
344     }
345
346     /**
347      * Says if an object exist on one of the container of the topology
348      * (excluding the local one).<p>
349      *
350      * @param name the name of the object to check
351      * @return true if the object has been found on one of the
352      * containers of the topology
353      */

354     public boolean exist(String JavaDoc name) {
355         if ( nameReps == null || nameReps.size() == 0 ) {
356             createNameReps();
357         }
358         // System.out.print ( " TEST THE EXISTANCE OF " + name + ".... " );
359
try {
360             for ( int i = 0; i < nameReps.size(); i++ ) {
361                 RemoteRef nr = (RemoteRef) nameReps.get(i);
362                 if ( ! nr.getRemCont().isLocal() ) {
363                     if ( ((Boolean JavaDoc)nr.invoke ( "isRegistered",
364                                                new Object JavaDoc[] { name } ))
365                          . booleanValue() ) {
366                         return true;
367                     }
368                 }
369             }
370         } catch (Exception JavaDoc e) {
371             System.out.println(e);
372             return true;
373         }
374         return false;
375     }
376
377     /**
378      * Get the index of a container.<p>
379      *
380      * @param container a container
381      * @return the index of the container, -1 if not part of this
382      * topology
383      * @see #getContainer(int)
384      * @see #getContainerIndex(String)
385      */

386     public int getContainerIndex(RemoteContainer container) {
387         return containers.indexOf(container);
388     }
389
390     /**
391      * Get the index of a container from its name.<p>
392      *
393      * @param name a container name
394      * @return the index of the container, -1 if not part of this
395      * topology
396      * @see #getContainer(int)
397      * @see #getContainerIndex(RemoteContainer)
398      * @see #getContainerIndexes(RE)
399      * @see #getContainerIndexes(String[])
400      */

401     public int getContainerIndex(String JavaDoc name) {
402         for ( int i = 0; i < containers.size(); i++ ) {
403             if ( ((RemoteContainer)containers.get( i )).getName().equals ( name ) ) {
404                 return i;
405             }
406         }
407         return -1;
408     }
409
410     /**
411      * Get the indexes of some container regarding a regular expression
412      * on the name.
413      *
414      * @param regexp a regular expression
415      * @return a set of matching containers indexes
416      *
417      * @see #getContainer(int)
418      * @see #getContainerIndex(String)
419      * @see #getContainerIndexes(String[])
420      */

421     public int[] getContainerIndexes(RE regexp) {
422         if ( regexp == null ) {
423             return null;
424         }
425         Vector JavaDoc temp = new Vector JavaDoc();
426         for ( int i = 0; i < containers.size(); i++ ) {
427             if ( regexp.isMatch( ((RemoteContainer)containers.get( i )).getName() ) ) {
428                 temp.add( new Integer JavaDoc( i ) );
429             }
430         }
431         int[] res = new int[temp.size()];
432         for ( int i = 0; i < res.length; i++ ) {
433             res[i] = ((Integer JavaDoc)temp.get(i)).intValue();
434         }
435         return res;
436     }
437
438     /**
439      * Get some containers regarding a regular expression on the name.
440      *
441      * @param regexp a regular expression
442      * @return a set of matching containers
443      *
444      * @see #getContainer(int)
445      * @see #getContainerIndex(String)
446      * @see #getContainerIndexes(String[])
447      * @see #getContainerIndexes(RE)
448      */

449     public RemoteContainer[] getContainers(RE regexp) {
450         if ( regexp == null ) {
451             return null;
452         }
453         Vector JavaDoc temp = new Vector JavaDoc();
454         for ( int i = 0; i < containers.size(); i++ ) {
455             if ( regexp.isMatch( ((RemoteContainer)containers.get(i)).getName() ) ) {
456                 temp.add(containers.get( i ));
457             }
458         }
459         RemoteContainer[] res = new RemoteContainer[temp.size()];
460         for ( int i = 0; i < res.length; i++ ) {
461             res[i] = (RemoteContainer)temp.get(i);
462         }
463         return res;
464     }
465
466     /**
467      * Get the indexes of some container names.<p>
468      *
469      * @param names an array containing the names
470      * @return the array of the corresponding indexes
471      *
472      * @see #getContainer(int)
473      * @see #getContainerIndex(RemoteContainer)
474      * @see #getContainerIndexes(RE)
475      */

476     public int[] getContainerIndexes(String JavaDoc[] names) {
477         int[] res = null;
478         Vector JavaDoc vres = new Vector JavaDoc();
479         if ( names != null && names.length != 0 ) {
480             for ( int i = 0; i < names.length; i++ ) {
481                 int index = getContainerIndex(
482                     RemoteContainer.resolve( names[i] ) );
483                 if ( index != -1 ) {
484                     vres.add( new Integer JavaDoc( index ) );
485                 }
486             }
487             res = new int[vres.size()];
488             for ( int i = 0; i < res.length; i++ ) {
489                 res[i] = ((Integer JavaDoc)vres.get(i)).intValue();
490             }
491         }
492         return res;
493     }
494
495     /**
496      * Add a container to the topology if not already present.
497      *
498      * @param container the container to add
499      *
500      * @see #addContainers(RemoteContainer[])
501      */

502     public void addContainer(RemoteContainer container) {
503         if( containers == null ) return;
504         if( containers.contains( container ) ) return;
505         containers.add(container);
506         fireTopologyChangeEvent();
507     }
508    
509     /**
510      * Adds a container from its name.
511      *
512      * @param container the container name
513      */

514     public void addContainer(String JavaDoc container) {
515         RemoteContainer rc = RemoteContainer.resolve( container );
516         addContainer( rc );
517     }
518
519     /**
520      * Add a set of containers to the topology.<p>
521      *
522      * @param someContainers a set of containers to add
523      *
524      * @see #addContainer(RemoteContainer)
525      */

526     public void addContainers(RemoteContainer[] someContainers) {
527         if( containers == null ) return;
528         for( int i=0; i < someContainers.length; i++ ) {
529             addContainer(someContainers[i]);
530         }
531     }
532
533     /**
534      * Remove a container from the topology.<p>
535      *
536      * @param container the container to be removed
537      */

538     public void removeContainer(RemoteContainer container) {
539         containers.remove(container);
540         fireTopologyChangeEvent();
541     }
542
543     /**
544      * Check if the current topology contains the given container.
545      *
546      * @param container the container to check
547      * @return true if the topology contains this container, false
548      * otherwise
549      */

550     public boolean isContainer(RemoteContainer container) {
551         return containers.contains(container);
552     }
553
554     /**
555      * Replace a container at a given index.<p>
556      *
557      * @param index the index where the container has to be substituted
558      * @param newContainer the container to set
559      *
560      * @see #replaceContainer(RemoteContainer,RemoteContainer)
561      */

562     public void replaceContainer(int index, RemoteContainer newContainer) {
563         if( newContainer == null ) return;
564         if( index < 0 || index >= containers.size() ) return;
565         if( containers.contains(newContainer) ) {
566             containers.remove(index);
567             fireTopologyChangeEvent();
568             return;
569         }
570         containers.remove(index);
571         containers.add(index,newContainer);
572         fireTopologyChangeEvent();
573     }
574
575     /**
576      * Replace a container by another container.<p>
577      *
578      * @param oldContainer the container to replace (must be in the topology)
579      * @param newContainer the replacing container
580      *
581      * @see #replaceContainer(int,RemoteContainer)
582      */

583     public void replaceContainer(RemoteContainer oldContainer,
584                                  RemoteContainer newContainer) {
585         replaceContainer(containers.indexOf(oldContainer),newContainer);
586     }
587
588     /**
589      * Gets a container from its name.
590      *
591      * @param name the name to seek
592      * @return the container, null if not found in the topology
593      */

594     public RemoteContainer getContainer(String JavaDoc name) {
595         RemoteContainer rc = RemoteContainer.resolve(name);
596         int index = containers.indexOf(rc);
597         if( index == -1 ) return null;
598         return (RemoteContainer)containers.get(index);
599     }
600
601     /**
602      * Returns the number of containers in this topology.<p>
603      *
604      * @return the containers count
605      */

606     public int countContainers() {
607         return containers.size();
608     }
609
610     /**
611      * Notifies everybody that the topology changed.
612      */

613     protected void fireTopologyChangeEvent() {
614         if( bootstrapFlag == false && this == Topology.get() ) {
615             loggerDist.debug("topology changed");
616             // notify all the system objects
617
Wrapping.invokeRoleMethod((Wrappee)ApplicationRepository.get(),
618                                       /* org.objectweb.jac.aspects.distribution.consistency.ConsistencyWrapper, */
619                                       "invalidateTopology",ExtArrays.emptyObjectArray);
620             Wrapping.invokeRoleMethod((Wrappee)Topology.get(),
621                                       /* org.objectweb.jac.aspects.distribution.consistency.ConsistencyWrapper, */
622                                       "invalidateTopology",ExtArrays.emptyObjectArray);
623             // notify the aspects
624
((ACManager)ACManager.get()).whenTopologyChanged();
625         }
626     }
627
628
629     /**
630      * Dump the containers of the topology.
631      */

632     public void dump () {
633         System.out.println ("Dumping the topology:");
634         System.out.println (containers);
635     }
636
637     /**
638      * Launches the administration GUI on the local container.
639      */

640     public void launchGUI(String JavaDoc programName) {
641         Object JavaDoc guiAC = ACManager.get().getObject("gui");
642         Object JavaDoc display = null;
643         try {
644             display = guiAC.getClass().getMethod("createSwingDisplay",
645                                                  new Class JavaDoc[] { Class JavaDoc.class } )
646                 .invoke(guiAC,
647                         new Object JavaDoc[] {Class.forName("org.objectweb.jac.aspects.gui.ProgramView")});
648             display.getClass().getMethod("setProgram",new Class JavaDoc[] {String JavaDoc.class})
649                 .invoke( display, new Object JavaDoc[] {programName});
650         } catch (Exception JavaDoc e) {
651             logger.error("launchGUI "+programName,e);
652         }
653     }
654
655     /**
656      * Start the admin GUI
657      */

658     public void launchGUI() {
659         Object JavaDoc guiAC = ACManager.get().getObject("gui");
660         Object JavaDoc display = null;
661         try {
662             display = guiAC.getClass().getMethod("createSwingDisplays",
663                                                  new Class JavaDoc[] { String JavaDoc[].class })
664                 .invoke(guiAC, new Object JavaDoc[] {new String JavaDoc[] {"admin"}});
665         } catch (Exception JavaDoc e) {
666             logger.error("launchGUI",e);
667         }
668     }
669
670     /**
671      * Start some swing GUIs for an application.
672      *
673      * @param application the name of the application for which to
674      * start the GUIs
675      * @param guiNames the names of the GUI windows to start
676      */

677     public void startSwingGUI(String JavaDoc application, String JavaDoc[] guiNames) {
678         loggerAspects.debug(
679             "Start Swing GUI: "+application+" "+Arrays.asList(guiNames));
680         ACManager acm = (ACManager)ACManager.get();
681         Object JavaDoc guiAC = acm.getObject(application+".gui");
682         // We use reflection here because we do not want to depend on
683
// the GuiAC
684
try {
685             Class JavaDoc guiACClass = Class.forName("org.objectweb.jac.aspects.gui.GuiAC");
686             Method JavaDoc method = guiACClass.getMethod("createSwingDisplays",
687                                                  new Class JavaDoc[] {String JavaDoc[].class});
688             method.invoke(guiAC,new Object JavaDoc[] {guiNames});
689         } catch (Exception JavaDoc e) {
690             logger.error("startSwingGUI "+application+","+Arrays.asList(guiNames),e);
691         }
692     }
693
694     /**
695      * Reload the configuration of an aspect
696      */

697     public void reloadAspect(String JavaDoc applicationName, String JavaDoc aspectName) {
698         ACManager.getACM().reloadAspect(applicationName,aspectName);
699     }
700
701     public void unweaveAspect(String JavaDoc applicationName, String JavaDoc aspectName) {
702         //Application app=ApplicationRepository.get().getApplication(applicationName);
703
ACManager.getACM().unregister(applicationName+"."+aspectName);
704     }
705
706     public void weaveAspect(String JavaDoc applicationName, String JavaDoc aspectClassName, String JavaDoc configPath) {
707         Application app=ApplicationRepository.get().getApplication(applicationName);
708         new ACConfiguration(app,aspectClassName,configPath,true).weave();
709     }
710
711     /**
712      * Set a trace logging level
713      * @see org.objectweb.jac.util.Log#trace(String,int,String)
714      */

715     public void setTrace(String JavaDoc application, String JavaDoc category, int level) {
716         loggerAspects.debug("Setting trace "+category+"="+level);
717         Logger.getLogger(category).setLevel(Level.toLevel(level));
718     }
719
720     /**
721      * Get a textual representation of the topology.
722      *
723      * @return a string describing the topology */

724
725     public String JavaDoc toString() {
726         if( containers == null ) return "null";
727         return containers.toString();
728     }
729    
730 }
731
Popular Tags