KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exolab > jms > net > orb > DefaultORB


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "Exolab" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of Exoffice Technologies. For written permission,
18  * please contact info@exolab.org.
19  *
20  * 4. Products derived from this Software may not be called "Exolab"
21  * nor may "Exolab" appear in their names without prior written
22  * permission of Exoffice Technologies. Exolab is a registered
23  * trademark of Exoffice Technologies.
24  *
25  * 5. Due credit should be given to the Exolab Project
26  * (http://www.exolab.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 2003-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42  *
43  * $Id: DefaultORB.java,v 1.9 2005/06/04 14:43:59 tanderson Exp $
44  */

45 package org.exolab.jms.net.orb;
46
47 import java.lang.reflect.InvocationTargetException JavaDoc;
48 import java.lang.reflect.Method JavaDoc;
49 import java.rmi.RemoteException JavaDoc;
50 import java.rmi.StubNotFoundException JavaDoc;
51 import java.rmi.ConnectException JavaDoc;
52 import java.rmi.server.ExportException JavaDoc;
53 import java.security.Principal JavaDoc;
54 import java.util.Map JavaDoc;
55
56 import org.apache.commons.logging.Log;
57 import org.apache.commons.logging.LogFactory;
58
59 import org.exolab.jms.common.security.BasicPrincipal;
60 import org.exolab.jms.net.connector.Authenticator;
61 import org.exolab.jms.net.connector.Caller;
62 import org.exolab.jms.net.connector.CallerListener;
63 import org.exolab.jms.net.connector.Connection;
64 import org.exolab.jms.net.connector.Invocation;
65 import org.exolab.jms.net.connector.InvocationHandler;
66 import org.exolab.jms.net.connector.MulticastCallerListener;
67 import org.exolab.jms.net.connector.Request;
68 import org.exolab.jms.net.connector.ResourceException;
69 import org.exolab.jms.net.connector.Response;
70 import org.exolab.jms.net.connector.AbstractConnectionManager;
71 import org.exolab.jms.net.proxy.Proxy;
72 import org.exolab.jms.net.registry.LocalRegistry;
73 import org.exolab.jms.net.registry.Registry;
74 import org.exolab.jms.net.uri.InvalidURIException;
75 import org.exolab.jms.net.uri.URI;
76 import org.exolab.jms.net.util.MethodHelper;
77
78
79 /**
80  * The <code>DefaultORB</code> class manages exported objects.
81  *
82  * @author <a HREF="mailto:tma@netspace.net.au">Tim Anderson</a>
83  * @version $Revision: 1.9 $ $Date: 2005/06/04 14:43:59 $
84  */

85 class DefaultORB extends AbstractORB {
86
87     /**
88      * The registry.
89      */

90     private LocalRegistry _registry;
91
92     /**
93      * The connection manager.
94      */

95     private AbstractConnectionManager _manager;
96
97     /**
98      * The caller event listeners.
99      */

100     private MulticastCallerListener _listeners;
101
102     /**
103      * Current caller.
104      */

105     private final ThreadLocal JavaDoc _caller = new ThreadLocal JavaDoc();
106
107     /**
108      * The logger.
109      */

110     private static final Log _log = LogFactory.getLog(DefaultORB.class);
111
112
113     /**
114      * Construct a new <code>DefaultORB</code> with the connection
115      * authenticator. All proxies will be loaded using this instance's class
116      * loader.
117      *
118      * @param authenticator the connection authenticator
119      * @throws RemoteException for any error
120      */

121     public DefaultORB(Authenticator authenticator)
122             throws RemoteException JavaDoc {
123         this(authenticator, DefaultORB.class.getClassLoader(), null);
124     }
125
126     /**
127      * Construct a new <code>DefaultORB</code> with the connection
128      * authenticator, and properties to configure the ORB. All proxies will be
129      * loaded using this instance's class loader.
130      *
131      * @param authenticator the connection authenticator
132      * @param properties properties to configure the ORB. May be
133      * <code>null</code>
134      * @throws RemoteException for any error
135      */

136     public DefaultORB(Authenticator authenticator, Map JavaDoc properties)
137             throws RemoteException JavaDoc {
138         this(authenticator, DefaultORB.class.getClassLoader(), properties);
139     }
140
141     /**
142      * Construct a new <code>DefaultORB</code> with properties to configure
143      * the ORB. Connections will be unauthenticated. All proxies will be loaded
144      * using this instance's class loader.
145      *
146      * @throws RemoteException for any error
147      */

148     public DefaultORB(Map JavaDoc properties) throws RemoteException JavaDoc {
149         this(new DummyAuthenticator(), DefaultORB.class.getClassLoader(),
150              properties);
151     }
152
153     /**
154      * Construct a new <code>DefaultORB</code>.
155      * Connections will be unauthenticated. All proxies will be loaded using
156      * this instance's class loader.
157      *
158      * @throws RemoteException for any error
159      */

160     public DefaultORB() throws RemoteException JavaDoc {
161         this(new DummyAuthenticator(), DefaultORB.class.getClassLoader(),
162              null);
163     }
164
165     /**
166      * Construct a new <code>DefaultORB</code> with the connection
167      * authenticator, the class loader used to load proxies, and properties
168      * to configure the ORB.
169      *
170      * @param authenticator the connection authenticator
171      * @param loader the class loader to load proxies
172      * @param properties properties to configure the ORB. May be
173      * <code>null</code>
174      * @throws RemoteException for any error
175      */

176     public DefaultORB(Authenticator authenticator, ClassLoader JavaDoc loader,
177                       Map JavaDoc properties)
178             throws RemoteException JavaDoc {
179         super(loader, properties);
180         if (authenticator == null) {
181             throw new IllegalArgumentException JavaDoc(
182                     "Argument 'authenticator' is null");
183         }
184
185         try {
186             _manager = createConnectionManager(new Handler(), authenticator);
187         } catch (ResourceException exception) {
188             throw new RemoteException JavaDoc("Failed to construct connection manager",
189                                       exception);
190         }
191     }
192
193     /**
194      * Returns a reference to the registry service.
195      *
196      * @return the registry service
197      * @throws RemoteException if the service cannot be exported
198      */

199     public synchronized LocalRegistry getRegistry() throws RemoteException JavaDoc {
200         if (_registry == null) {
201             _registry = new RegistryService(this);
202         }
203         return _registry;
204     }
205
206     /**
207      * Returns a reference to a remote registry service.
208      *
209      * @param properties the connection properties.
210      * @return the registry service
211      * @throws RemoteException for any error
212      */

213     public Registry getRegistry(Map JavaDoc properties) throws RemoteException JavaDoc {
214         if (properties == null || properties.get(PROVIDER_URI) == null) {
215             throw new ConnectException JavaDoc(PROVIDER_URI + " not specified");
216         }
217         Registry registry;
218         String JavaDoc uri = (String JavaDoc) properties.get(PROVIDER_URI);
219         String JavaDoc principal = (String JavaDoc) properties.get(SECURITY_PRINCIPAL);
220         String JavaDoc credentials = (String JavaDoc) properties.get(SECURITY_CREDENTIALS);
221         Principal JavaDoc subject = null;
222
223         if (principal != null) {
224             subject = new BasicPrincipal(principal, credentials);
225         }
226
227         try {
228             registry = Locator.getRegistry(subject, uri, _manager,
229                                            getProxyClassLoader(),
230                                            properties);
231         } catch (InvalidURIException exception) {
232             throw new RemoteException JavaDoc("Invalid URI: " + uri, exception);
233         }
234         return registry;
235     }
236
237     /**
238      * Export an object to the current remote caller. Only the remote caller may
239      * perform invocations.
240      *
241      * @param object the object to export
242      * @return a proxy which may be used to invoke methods on the object
243      * @throws ExportException if the object cannot be exported
244      * @throws StubNotFoundException if the proxy class cannot be found
245      */

246     public Proxy exportObjectTo(Object JavaDoc object) throws ExportException JavaDoc,
247             StubNotFoundException JavaDoc {
248         Caller caller = (Caller) _caller.get();
249         if (caller == null) {
250             throw new ExportException JavaDoc("Cannot export - no current caller");
251         }
252         return doExportTo(object, caller.getLocalURI());
253     }
254
255     /**
256      * Returns the current caller.
257      *
258      * @return the current caller, or <code>null</code> if no call is in
259      * progress
260      * @throws RemoteException for any error
261      */

262     public Caller getCaller() throws RemoteException JavaDoc {
263         return (Caller) _caller.get();
264     }
265
266     /**
267      * Register a caller event listener.
268      *
269      * @param uri the remote URI to listen on
270      * @param listener the listener to notify
271      * @throws InvalidURIException if <code>uri</code> is invalid
272      */

273     public void addCallerListener(String JavaDoc uri, CallerListener listener)
274             throws InvalidURIException {
275         synchronized (this) {
276             if (_listeners == null) {
277                 _listeners = new MulticastCallerListener();
278                 _manager.setCallerListener(_listeners);
279             }
280         }
281         _listeners.addCallerListener(uri, listener);
282     }
283
284     /**
285      * Deregister a caller event listener.
286      *
287      * @param uri the remote URI the listener is listening for events on
288      * @param listener the listener to remove
289      * @throws InvalidURIException if <code>uri</code> is invalid
290      */

291     public void removeCallerListener(String JavaDoc uri, CallerListener listener)
292         throws InvalidURIException {
293         MulticastCallerListener listeners = null;
294         synchronized (this) {
295             listeners = _listeners;
296         }
297         if (listeners != null) {
298             listeners.removeCallerListener(uri, listener);
299         }
300     }
301
302     /**
303      * Shuts down the ORB.
304      *
305      * @throws RemoteException for any error
306      */

307     public void shutdown() throws RemoteException JavaDoc {
308         try {
309             _manager.close();
310         } catch (ResourceException exception) {
311             throw new RemoteException JavaDoc("Failed to close connection manager",
312                                       exception);
313         }
314         // super.close(); @todo
315
}
316
317     /**
318      * Creates a new connection manager.
319      *
320      * @param handler the invocation handler
321      * @param authenticator the connection authenticator
322      * @return a new connection manager
323      * @throws ResourceException for any error
324      */

325     protected AbstractConnectionManager createConnectionManager(
326             InvocationHandler handler, Authenticator authenticator)
327         throws ResourceException {
328         return new DefaultConnectionManager(handler, authenticator,
329                                             getProperties());
330     }
331
332     /**
333      * Connect to the specified URI.
334      *
335      * @param uri the URI to establish a connection with
336      * @param principal specifies the identity of the principal. If
337      * <code>null</code>, indicates to connect anonymously.
338      * @param credentials the credentials of the principal
339      * @return the local address that the connection is bound to
340      * @throws ExportException for any error
341      */

342     protected URI connect(URI uri, String JavaDoc principal, String JavaDoc credentials)
343             throws ExportException JavaDoc {
344         URI result;
345         try {
346             Principal JavaDoc subject = null;
347             if (principal != null) {
348                 subject = new BasicPrincipal(principal, credentials);
349             }
350             Connection connection = _manager.getConnection(subject, uri);
351             result = connection.getLocalURI();
352         } catch (ResourceException exception) {
353             throw new ExportException JavaDoc("Failed to connect to URI: " + uri,
354                                       exception);
355         }
356         return result;
357     }
358
359     /**
360      * Accept connections on the specified URI.
361      *
362      * @param uri the URI to accept connections on
363      * @throws ExportException for any error
364      */

365     protected void accept(URI uri) throws ExportException JavaDoc {
366         try {
367             _manager.accept(uri, getProperties());
368         } catch (ResourceException exception) {
369             throw new ExportException JavaDoc("Failed to accept connections on URI: "
370                                       + uri, exception);
371         }
372     }
373
374     /**
375      * Returns the method corresponding to the supplied object and method
376      * identifier.
377      *
378      * @param object the object to locate the method for
379      * @param methodID the method identifier
380      * @return the method
381      * @throws NoSuchMethodException if a corresponding method cannot be found
382      */

383     private Method JavaDoc getMethod(Object JavaDoc object, long methodID)
384             throws NoSuchMethodException JavaDoc {
385
386         Method JavaDoc result = null;
387         Method JavaDoc[] methods = MethodHelper.getAllInterfaceMethods(
388                 object.getClass());
389         for (int i = 0; i < methods.length; ++i) {
390             Method JavaDoc method = methods[i];
391             if (MethodHelper.getMethodID(method) == methodID) {
392                 result = method;
393                 break;
394             }
395         }
396         if (result == null) {
397             throw new NoSuchMethodException JavaDoc(
398                     "Failed to resolve method for methodID=" + methodID);
399         }
400         return result;
401     }
402
403     /**
404      * Invocation handler, that delegates invocations to objects managed by the
405      * DefaultORB.
406      */

407     private class Handler implements InvocationHandler {
408
409         /**
410          * Prepare for an invocation.
411          */

412         public void prepare() {
413             // no-op
414
}
415
416         /**
417          * Handle a method invocation and return the result.
418          *
419          * @param request the request
420          * @param caller the caller performing the invocation
421          * @return the result of the invocation
422          */

423         public Response invoke(Request request, Caller caller) {
424             Response response;
425             try {
426                 Object JavaDoc object = getObject(request.getObjID(),
427                                           request.getURI());
428                 Method JavaDoc method = request.getMethod();
429                 if (method == null) {
430                     // resolve the method using its id
431
method = getMethod(object, request.getMethodID());
432                 }
433                 Object JavaDoc[] args = request.getArgs();
434                 if (args == null) {
435                     // deserialize the arguments
436
args = request.readArgs(method);
437                 }
438                 if (_log.isDebugEnabled()) {
439                     _log.debug("Invoking " + method + " on " + object);
440                 }
441                 _caller.set(caller);
442                 Object JavaDoc result = method.invoke(object, args);
443                 response = new Response(result, method);
444             } catch (InvocationTargetException JavaDoc exception) {
445                 Throwable JavaDoc target = exception.getTargetException();
446                 if (target == null) {
447                     target = exception;
448                 }
449                 response = new Response(target);
450             } catch (Throwable JavaDoc exception) {
451                 response = new Response(exception);
452             } finally {
453                 _caller.set(null);
454             }
455             return response;
456         }
457
458         /**
459          * Perform an invocation.
460          *
461          * @param invocation the invocation
462          */

463         public void invoke(Invocation invocation) {
464             Response response;
465             try {
466                 Request request = invocation.getRequest();
467                 Caller caller = invocation.getCaller();
468                 response = invoke(request, caller);
469             } catch (Throwable JavaDoc exception) {
470                 response = new Response(exception);
471             }
472
473             invocation.setResponse(response);
474         }
475
476     }
477
478     /**
479      * Dummy connection authenticator, which simply flags all principals as
480      * authenticated.
481      */

482     private static class DummyAuthenticator implements Authenticator {
483
484         /**
485          * Determines if a principal has permissions to connect
486          *
487          * @param principal the principal to check
488          * @return <code>true</code> if the principal has permissions to
489          * connect
490          * @throws ResourceException if an error occurs
491          */

492         public boolean authenticate(Principal JavaDoc principal)
493                 throws ResourceException {
494             return true;
495         }
496     }
497
498 }
499
Popular Tags