KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2   Copyright (C) 2001-2003 Lionel Seinturier, Renaud Pawlak.
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 Generaly 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 java.io.Serializable JavaDoc;
21 import java.lang.reflect.Constructor JavaDoc;
22 import java.lang.reflect.InvocationTargetException JavaDoc;
23 import java.lang.reflect.Method JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import org.apache.log4j.Logger;
26 import org.objectweb.jac.core.ACManager;
27 import org.objectweb.jac.core.Collaboration;
28 import org.objectweb.jac.core.JacLoader;
29 import org.objectweb.jac.core.JacPropLoader;
30 import org.objectweb.jac.core.NameRepository;
31 import org.objectweb.jac.core.ObjectRepository;
32 import org.objectweb.jac.core.SerializedJacObject;
33 import org.objectweb.jac.core.Wrappee;
34 import org.objectweb.jac.core.Wrapping;
35 import org.objectweb.jac.core.rtti.ClassRepository;
36 import org.objectweb.jac.util.ExtArrays;
37 import org.objectweb.jac.util.WrappedThrowableException;
38
39 /**
40  * RemoteContainer is used as a delegate by daemons (Distd) that hold
41  * remote objects.<p>
42  *
43  * A remote container enables JAC objects to access and manipulate
44  * objects located on other Java VMs.
45  *
46  * @see org.objectweb.jac.core.dist.Distd
47  *
48  * @author <a HREF="http://www-src.lip6.fr/homepages/Lionel.Seinturier/index-eng.html">Lionel Seinturier</a>
49  * @author <a HREF="http://cedric.cnam.fr/~pawlak/index-english.html">Renaud Pawlak</a> */

50  
51 public class RemoteContainer implements Serializable JavaDoc {
52     static Logger logger = Logger.getLogger("dist");
53     static Logger loggerSerial = Logger.getLogger("serialization");
54
55     /** Verbose tells whether information message should be printed or
56         not. */

57     public static boolean verbose = false;
58
59     /** The name of the container. */
60     public String JavaDoc name = "theContainerWithNoName";
61
62     /** Property key for the class providing a naming service. */
63     //protected static final String namingClassProp = "org.objectweb.jac.core.dist.namingClass";
64

65     /** Default class providing a naming service. */
66     //protected static final String namingClassDefaultName = "org.objectweb.jac.core.dist.rmi.RMINaming";
67

68     /**
69      * This method dynamically binds the local container to a new
70      * remote container.
71      *
72      * @param name the remote container to bind to */

73
74     public static RemoteContainer bindNewContainer(String JavaDoc name) {
75
76         logger.debug("binding to a new container "+name);
77         RemoteContainer result = null;
78         // check is the container already bounded
79
result=Topology.get().getContainer(name);
80         if (result != null) {
81             logger.debug("container already bound");
82             return result;
83         } else {
84             result = RemoteContainer.resolve(name);
85             if (result == null) {
86                 throw new RuntimeException JavaDoc("container "+name+" does not exist");
87             }
88         }
89
90         // get the remote topology
91
RemoteRef remoteTopology = result.bindTo("JAC_topology");
92
93         // add the local known containers to the remote topology
94
RemoteContainer[] rcs = Topology.get().getContainers();
95         remoteTopology.invoke("addContainers", new Object JavaDoc[] {rcs});
96
97         // add all the remote containers to the local topology
98
rcs = (RemoteContainer[])remoteTopology.invoke("getContainers",ExtArrays.emptyObjectArray);
99         Topology.get().addContainers(rcs);
100         return result;
101     }
102
103     /**
104      * Create a new container.
105      *
106      * @param verbose true if information messages are to be printed
107      */

108     public RemoteContainer(boolean verbose) {
109         RemoteContainer.verbose = verbose;
110     }
111
112     /**
113      * Create a new container and instantiates an object.
114      *
115      * @param className the name of the class to instantiate
116      * @param verbose true if information messages are to be printed
117      */

118     public RemoteContainer(String JavaDoc className, boolean verbose) {
119         try {
120             Class.forName(className).newInstance();
121         } catch (Exception JavaDoc e) {
122             logger.error("RemoteContainer "+className,e);
123         }
124         RemoteContainer.verbose = verbose;
125     }
126    
127     /**
128      * Create a new empty container.
129      * This constructor is needed by the compiler when one tries
130      * to subclass RemoteContainer.
131      *
132      * @see org.objectweb.jac.core.dist.rmi.RMIRemoteContainerStub
133      */

134     public RemoteContainer() {}
135
136     /**
137      * Getter method for field name.<p>
138      *
139      * @return the container name
140      */

141     public String JavaDoc getName() {
142         return name;
143     }
144    
145
146     /**
147      * Setter method for field name.<p>
148      *
149      * Note that this method does not bind the container. It simply
150      * sets the value of field name. Use resolve(name) to bind a
151      * container to a name.<p>
152      *
153      * The name can be an incomplete name since it is completed by the
154      * <code>getFullHostName</code> method.
155      *
156      * @param name the name of the container
157      * @see #resolve(String)
158      * @see Distd#getFullHostName(String) */

159
160     public void setName(String JavaDoc name) {
161         this.name = Distd.getFullHostName(name);
162     }
163
164     /**
165      * Return true if the container is local.<p>
166      *
167      * @param name the container name to resolve
168      * @return true if the container is local.
169      * @see #resolve(String)
170      * @see #isLocal()
171      */

172     public static boolean isLocal(String JavaDoc name) {
173         RemoteContainer rc = RemoteContainer.resolve(name);
174         if (rc==null)
175             return false;
176         return rc.isLocal();
177     }
178    
179     /**
180      * This class method resolve a container from its name.
181      * The way the resolution is performed is protocol dependent.<p>
182      *
183      * Property org.objectweb.jac.dist.remoteContainerClass defines the class of
184      * the actual RemoteContainer returned (e.g. CORBARemoteContainer).
185      * If the property is not defined or
186      * if the class does not exist, RMIRemoteContainer is the default.
187      *
188      * @param name the name of the container
189      * @return the container reference
190      */

191     public static RemoteContainer resolve(String JavaDoc name)
192     {
193         logger.debug("resolving remote container "+name);
194
195         RemoteContainer remoteContainer = null;
196       
197         /** Lookup the actual remote container class name from the properties. */
198
199         String JavaDoc namingClassName = JacPropLoader.namingClassName;
200         /*
201           String namingClassName = null;
202           if (JacObject.props != null) {
203           namingClassName = JacObject.props.getProperty(namingClassProp);
204           }
205
206         */

207         if (namingClassName == null) {
208             namingClassName = JacPropLoader.namingClassDefaultName;
209         }
210       
211         /** Invoke the class method resolve on the above mentioned class. */
212       
213         try {
214             Class JavaDoc namingClass = Class.forName(namingClassName);
215
216             Method JavaDoc meth =
217                 namingClass.getMethod( "resolve", new Class JavaDoc[]{String JavaDoc.class} );
218
219             remoteContainer =
220                 (RemoteContainer) meth.invoke(null, new Object JavaDoc[]{name});
221       
222         } catch (Exception JavaDoc e) {
223             logger.error("resolve "+name,e);
224             throw new RuntimeException JavaDoc(e.toString());
225         }
226
227         logger.debug("resolve is returning " + remoteContainer);
228       
229         return remoteContainer;
230     }
231
232
233     /**
234      * Return true if the container is local.<p>
235      *
236      * RemoteContainer objects are always locals. RemoteContainer
237      * stubs objects (see RMIRemoteContainerStub) may not always be
238      * local.
239      *
240      * @return true if the container is local.
241      * @see Distd#containsContainer(RemoteContainer) */

242
243     public boolean isLocal() {
244         return Distd.containsContainer( this );
245     }
246
247     /**
248      * This method instantiates a className object.<p>
249      *
250      * Clients call it to remotely instantiate an object.
251      * <code>instantiates</code> creates an object and returns its
252      * local JAC index.<p>
253      *
254      * The object's name can be null. If not, the object is
255      * registered into the local repository.<p>
256      *
257      * The Aspect Component Manager is upcalled to notify the system
258      * from a remote instantiation.<p>
259      *
260      * @param name the name of the object
261      * @param className the class name to instantiate
262      * @param args initialization arguments for the instantiation
263      * @param fields the object fields that are part of the state
264      * @param state the state to copy
265      * @return the index of the instantiated object
266      *
267      * @see org.objectweb.jac.core.ACManager#whenRemoteInstantiation(Wrappee,String)
268      */

269     public int instantiates(String JavaDoc name, String JavaDoc className, Object JavaDoc[] args,
270                             String JavaDoc[] fields, byte[] state, byte[] collaboration)
271     {
272         /** Set the local interaction */
273         Collaboration.set(
274             (Collaboration)SerializedJacObject.deserialize(collaboration));
275
276         logger.debug("remote instantiation of "+className);
277
278         Object JavaDoc substance = null;
279       
280         try {
281
282             /** Instantiate the base object */
283          
284             Class JavaDoc substanceClass = null;
285          
286             try {
287                 /** Begin critical section */
288                 // WAS THIS REALLY USEFUL ????
289
//JacObject.remoteInstantiation = true;
290

291                 substanceClass = Class.forName(className);
292
293                 if (args == null) {
294                     Constructor JavaDoc c = substanceClass.getConstructor (
295                         new Class JavaDoc[] {});
296                     substance = c.newInstance(new Object JavaDoc[] {});
297                 } else {
298                     throw new InstantiationException JavaDoc(
299                         "No arguments allowed when remote instantiation");
300                 }
301
302                 /** End critical section */
303                 // USEFULL ????
304
///JacObject.remoteInstantiation = false;
305

306             } catch(Exception JavaDoc e) {
307                 // USEFUL????
308
//JacObject.remoteInstantiation = false;
309
logger.error("Instantiates "+name+" "+className+Arrays.asList(args),e);
310                 return -1;
311             }
312
313             /** Copy the transmitted state if needed */
314             
315             if (fields != null && state != null) {
316                 Object JavaDoc[] dstate = (Object JavaDoc[])
317                     SerializedJacObject.deserialize(state);
318             
319                 ObjectState.setState(
320                     substance,new Object JavaDoc[] { fields, dstate }
321                 );
322                 loggerSerial.debug("deserialized fields="+
323                           Arrays.asList(fields)+"; state="+Arrays.asList(dstate));
324             } else {
325                 loggerSerial.debug("deserialize: transmitted state is empty");
326             }
327          
328             if (verbose) {
329                 System.out.println(
330                     "--- A " + className + " instance has been created (" +
331                     ObjectRepository.getMemoryObjectIndex(substance) + ") ---"
332                 );
333             }
334          
335         } catch (Exception JavaDoc e) {
336             logger.error("Instantiates "+name+" "+className+Arrays.asList(args),e);
337             return -1;
338         }
339
340         /** Upcall the ACManager to notify it from a remote instatiation. */
341         ((ACManager) ACManager.get()).whenRemoteInstantiation( (Wrappee) substance, name );
342       
343         return ObjectRepository.getMemoryObjectIndex(substance);
344     }
345
346     /**
347      * Copy a state into a base object.
348      *
349      * @param index the base object index (see <code>org.objectweb.jac.core.JacObject</code>)
350      * @param fields the object fields that are part of the state
351      * @param state the state to copy
352      */

353     
354     public void copy(String JavaDoc name, int index, String JavaDoc[] fields, byte[] state,
355                      byte[] collaboration) {
356
357         /** Set the local interaction */
358         Collaboration.set((Collaboration)SerializedJacObject.deserialize(collaboration));
359         ObjectState.setState(ObjectRepository.getMemoryObject(index), new Object JavaDoc[] {
360             fields, (Object JavaDoc[]) SerializedJacObject.deserialize(state) } );
361
362         /** upcall the acmanager ??? */
363     }
364    
365    
366     /**
367      * Invoke a method on a base object.<p>
368      *
369      * The base object is the remote counterpart of a local object that
370      * has been remotely instantiated by the <code>Distd</code> daemon.
371      *
372      * @param index the callee index (see org.objectweb.jac.core.JacObject)
373      * @param methodName the called method name
374      * @param args the called method arguments
375      * @param collaboration the collaboration coming from the calling host
376      * @return the result as an array of bytes (to be deserialized) */

377    
378     public byte[] invoke(int index, String JavaDoc methodName, byte[] args,
379                          byte[] collaboration) {
380
381         if (args != null)
382             Distd.inputCount += args.length;
383
384         Object JavaDoc[] methodArgs =
385             (Object JavaDoc[])SerializedJacObject.deserializeArgs(args);
386       
387         Object JavaDoc ret = null;
388
389         try {
390             Object JavaDoc substance = ObjectRepository.getMemoryObject(index);
391             Class JavaDoc substanceClass = substance.getClass();
392          
393             /** Set the local interaction */
394             Collaboration.set((Collaboration)SerializedJacObject.
395                               deserialize(collaboration));
396
397             logger.debug("remote invocation of " + methodName + " on "+
398                          substance + "("+
399                          NameRepository.get().getName(substance)+")");
400          
401             ret = ClassRepository.invokeDirect(substanceClass, methodName,
402                                                substance, methodArgs);
403          
404         } catch (InvocationTargetException JavaDoc e) {
405             if (e.getTargetException() instanceof WrappedThrowableException) {
406                 throw (RuntimeException JavaDoc)e.getTargetException();
407             } else {
408                 logger.error("invoke "+index+"."+methodName+
409                              Arrays.asList(methodArgs),e);
410             }
411         } catch (Exception JavaDoc e) {
412             logger.error("invoke "+index+"."+methodName+
413                          Arrays.asList(methodArgs),e);
414         }
415         /*catch( IllegalAccessException e ) {
416           e.printStackTrace();
417           return null;
418           }
419           catch ( NoSuchMethodException e ) {
420           System.out.println ( "Error: invoke '" + methodName +
421           "' with " + Arrays.asList(methodArgs) + "." );
422           }*/

423
424         byte[] sret = SerializedJacObject.serialize(ret);
425
426         if (sret != null)
427             Distd.outputCount += sret.length;
428         logger.debug("remote invocation ok, returning "+ret);
429         return sret;
430     }
431
432     public byte[] invokeRoleMethod(int index, String JavaDoc methodName, byte[] args,
433                                    byte[] collaboration) {
434
435         if (args != null)
436             Distd.inputCount += args.length;
437
438         Object JavaDoc[] methodArgs =
439             (Object JavaDoc[])
440             SerializedJacObject.deserialize(args);
441       
442         Object JavaDoc ret = null;
443
444         try {
445          
446             Object JavaDoc substance = ObjectRepository.getMemoryObject(index);
447             Class JavaDoc substanceClass = substance.getClass();
448          
449             /** Set the local interaction */
450
451             logger.debug(Collaboration.get().toString());
452
453             Collaboration.set((Collaboration)SerializedJacObject
454                               .deserialize(collaboration));
455          
456          
457             logger.debug("remote invocation of role method " + methodName + " on "+
458                       substance + "("+
459                       NameRepository.get().getName(substance)+")"+
460                       " - "+this);
461             logger.debug(Collaboration.get().toString());
462          
463             ret=Wrapping.invokeRoleMethod((Wrappee)substance,methodName,methodArgs);
464          
465             logger.debug(Collaboration.get().toString());
466         } catch(Exception JavaDoc e) {
467             if (e instanceof WrappedThrowableException) {
468                 throw (RuntimeException JavaDoc)e;
469             } else {
470                 logger.error("invokeRoleMethod "+index+"."+methodName+
471                              Arrays.asList(methodArgs),e);
472             }
473         }
474
475         byte[] sret = SerializedJacObject.serialize(ret);
476
477         if (sret != null)
478             Distd.outputCount += sret.length;
479
480         logger.debug("remote invocation ok, returning "+ret);
481
482         return sret;
483     }
484
485
486     /**
487      * Gets the bytecode for the given class by using the current
488      * loader.<p>
489      *
490      * This method is used by distributed loaders to fetch classes
491      * bytecodes from JAC remote containers that are classes
492      * repositories.<p>
493      *
494      * @param className the class name
495      * @return the corresponding bytecode
496      */

497
498     public byte[] getByteCodeFor(String JavaDoc className) {
499         ClassLoader JavaDoc cl = getClass().getClassLoader();
500         if (cl instanceof JacLoader) {
501             logger.debug("getByteCodeFor "+className+" bootstraping");
502             /** we are a bootstraping site */
503             try {
504                 if (Wrappee.class.isAssignableFrom(Class.forName(className))) {
505                     //( ((JacLoader)cl).getClassPath().readClassfile( className ) );
506
return null;
507                 }
508             } catch ( Exception JavaDoc e ) {
509                 logger.error("Failed to fetch bytecode for "+className,e);
510             }
511         } else if (cl instanceof DistdClassLoader) {
512             logger.debug("getByteCodeFor "+className+" distd");
513             ((DistdClassLoader)cl).getByteCode(className);
514         }
515         logger.debug("getByteCodeFor "+className+" -> null");
516         return null;
517     }
518
519     /**
520      * Returns a remote reference on the object corresponding to the
521      * given name.<p>
522      *
523      * Note: This method has been added for practical reason but
524      * introduces a implicit dependency towards the naming aspect. If
525      * the naming aspect is not woven, then this method does not mean
526      * anything and the returned remote reference is null.
527      *
528      * @param name the name of the object to bind to
529      * @return the corresponding remote reference */

530
531     public RemoteRef bindTo(String JavaDoc name) {
532         Class JavaDoc nrc = null;
533         Method JavaDoc m = null;
534         Object JavaDoc nr = null;
535         Object JavaDoc o = null;
536
537         logger.debug("client is binding to "+name);
538
539         o = NameRepository.get().getObject(name);
540         if (o == null) {
541             logger.debug("object "+name+" not found on this container");
542             return null;
543         }
544        
545         RemoteContainer rc = RemoteContainer.resolve(this.name);
546         int index = ObjectRepository.getMemoryObjectIndex(o);
547
548         RemoteRef rr = RemoteRef.create(name, rc, index);
549       
550         logger.debug("returning remote reference "+rr);
551
552         return rr;
553     }
554
555     /**
556      * Check the equality of two containers (on the name).<p>
557      *
558      * @param container the container to check
559      * @return true if the given container equals to the current container
560      */

561
562     public boolean equals(Object JavaDoc container) {
563         if (!(container instanceof RemoteContainer))
564             return false;
565         RemoteContainer c = (RemoteContainer)container;
566       
567         return name.equals(c.getName());
568     }
569    
570     /**
571      * Return a textual representation of a container (its name).
572      *
573      * @return a textual representation of the container */

574
575     public String JavaDoc toString() {
576         return "Container " + getName();
577     }
578
579     /**
580      * Launches a administration GUI on a remote container.
581      */

582
583     public void launchRemoteGUI() {
584         RemoteContainer rc = RemoteContainer.resolve( name );
585         logger.debug("launch remote GUI: container = " + rc );
586         RemoteRef remoteTopology = rc.bindTo( "JAC_topology" );
587         logger.debug("remote topology = " + remoteTopology );
588
589         /*Object guiAC = ACManager.get().getObject("gui");
590           Object display = null;
591           String programName = null;
592           try {
593           display = guiAC.getClass().getMethod( "getDisplay", new Class[] { String.class } )
594           .invoke( guiAC, new Object[] { "admin" } );
595           programName = (String)display.getClass().getMethod("getProgram",ExtArrays.emptyClassArray)
596           .invoke( display, ExtArrays.emptyObjectArray);
597           } catch (Exception e) { e.printStackTrace(); return; }*/

598         remoteTopology.invoke( "launchGUI", ExtArrays.emptyObjectArray );
599     }
600    
601 }
602
Popular Tags