KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > invocation > jrmp > server > JRMPInvoker


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.invocation.jrmp.server;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.net.InetAddress JavaDoc;
26 import java.net.UnknownHostException JavaDoc;
27 import java.io.Serializable JavaDoc;
28 import java.rmi.server.RemoteServer JavaDoc;
29 import java.rmi.server.UnicastRemoteObject JavaDoc;
30 import java.rmi.server.RMIServerSocketFactory JavaDoc;
31 import java.rmi.server.RMIClientSocketFactory JavaDoc;
32 import java.rmi.server.RemoteStub JavaDoc;
33 import java.rmi.MarshalledObject JavaDoc;
34 import java.security.PrivilegedAction JavaDoc;
35 import java.security.AccessController JavaDoc;
36 import java.security.PrivilegedExceptionAction JavaDoc;
37 import java.security.PrivilegedActionException JavaDoc;
38
39 import javax.management.ObjectName JavaDoc;
40 import javax.management.MBeanRegistration JavaDoc;
41 import javax.management.MBeanServer JavaDoc;
42 import javax.naming.Name JavaDoc;
43 import javax.naming.InitialContext JavaDoc;
44 import javax.naming.Context JavaDoc;
45 import javax.naming.NamingException JavaDoc;
46 import javax.naming.NameNotFoundException JavaDoc;
47 import javax.transaction.Transaction JavaDoc;
48
49 import org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy;
50 import org.jboss.invocation.Invocation;
51 import org.jboss.invocation.Invoker;
52 import org.jboss.invocation.MarshalledInvocation;
53 import org.jboss.invocation.MarshalledValueInputStream;
54 import org.jboss.logging.Logger;
55 import org.jboss.mx.util.JMXExceptionDecoder;
56 import org.jboss.net.sockets.DefaultSocketFactory;
57 import org.jboss.security.SecurityDomain;
58 import org.jboss.system.Registry;
59 import org.jboss.system.ServiceMBeanSupport;
60 import org.jboss.tm.TransactionPropagationContextImporter;
61 import org.jboss.tm.TransactionPropagationContextUtil;
62
63 /**
64  * The JRMPInvoker is an RMI implementation that can generate Invocations
65  * from RMI/JRMP into the JMX base.
66  *
67  * @author <a HREF="mailto:marc.fleury@jboss.org>Marc Fleury</a>
68  * @author <a HREF="mailto:scott.stark@jboss.org>Scott Stark</a>
69  * @version $Revision: 37459 $
70  * @jmx.mbean extends="org.jboss.system.ServiceMBean"
71  */

72 public class JRMPInvoker
73    extends RemoteServer JavaDoc
74    implements Invoker, JRMPInvokerMBean, MBeanRegistration JavaDoc
75 {
76    /**
77     * Identifer to instruct the usage of an anonymous port.
78     */

79    public static final int ANONYMOUS_PORT = 0;
80
81    /**
82     * Instance logger.
83     */

84    protected Logger log;
85
86    /**
87     * Service MBean support delegate.
88     */

89    protected ServiceMBeanSupport support;
90
91    /**
92     * The port the container will be exported on
93     */

94    protected int rmiPort = ANONYMOUS_PORT;
95
96    /**
97     * An optional custom client socket factory
98     */

99    protected RMIClientSocketFactory JavaDoc clientSocketFactory;
100
101    /**
102     * An optional custom server socket factory
103     */

104    protected RMIServerSocketFactory JavaDoc serverSocketFactory;
105
106    /**
107     * The class name of the optional custom client socket factory
108     */

109    protected String JavaDoc clientSocketFactoryName;
110
111    /**
112     * The class name of the optional custom server socket factory
113     */

114    protected String JavaDoc serverSocketFactoryName;
115
116    /**
117     * The address to bind the rmi port on
118     */

119    protected String JavaDoc serverAddress;
120    /**
121     * The name of the security domain to use with server sockets that support SSL
122     */

123    protected String JavaDoc sslDomain;
124
125    protected RemoteStub JavaDoc invokerStub;
126    /**
127     * The socket accept backlog
128     */

129    protected int backlog = 200;
130    /**
131     * A flag to enable caching of classes in the MarshalledValueInputStream
132     */

133    protected boolean enableClassCaching = false;
134    /**
135     * A priviledged actions for MBeanServer.invoke when running with sec mgr
136     */

137    private MBeanServerAction serverAction = new MBeanServerAction();
138
139    private static TransactionPropagationContextImporter tpcImporter;
140
141    public JRMPInvoker()
142    {
143       final JRMPInvoker delegate = this;
144
145       // adapt the support delegate to invoke our state methods
146
support = new ServiceMBeanSupport(getClass())
147       {
148          protected void startService() throws Exception JavaDoc
149          {
150             delegate.startService();
151          }
152          protected void stopService() throws Exception JavaDoc
153          {
154             delegate.stopService();
155          }
156          protected void destroyService() throws Exception JavaDoc
157          {
158             delegate.destroyService();
159          }
160       };
161
162       // Setup logging from delegate
163
log = support.getLog();
164    }
165
166    /**
167     * @jmx.managed-attribute
168     */

169    public int getBacklog()
170    {
171       return backlog;
172    }
173
174    /**
175     * @jmx.managed-attribute
176     */

177    public void setBacklog(int back)
178    {
179       backlog = back;
180    }
181
182    /**
183     * @jmx.managed-attribute
184     */

185    public boolean getEnableClassCaching()
186    {
187       return enableClassCaching;
188    }
189
190    /**
191     * @jmx.managed-attribute
192     */

193    public void setEnableClassCaching(boolean flag)
194    {
195       enableClassCaching = flag;
196       MarshalledValueInputStream.useClassCache(enableClassCaching);
197    }
198
199    /**
200     * @return The localhost name or null.
201     */

202    public String JavaDoc getServerHostName()
203    {
204       try
205       {
206          return InetAddress.getLocalHost().getHostName();
207       }
208       catch (Exception JavaDoc ignored)
209       {
210          return null;
211       }
212    }
213
214    /**
215     * @jmx.managed-attribute
216     */

217    public void setRMIObjectPort(final int rmiPort)
218    {
219       this.rmiPort = rmiPort;
220    }
221
222    /**
223     * @jmx.managed-attribute
224     */

225    public int getRMIObjectPort()
226    {
227       return rmiPort;
228    }
229
230    /**
231     * @jmx.managed-attribute
232     */

233    public void setRMIClientSocketFactory(final String JavaDoc name)
234    {
235       clientSocketFactoryName = name;
236    }
237
238    /**
239     * @jmx.managed-attribute
240     */

241    public String JavaDoc getRMIClientSocketFactory()
242    {
243       return clientSocketFactoryName;
244    }
245
246    /**
247     * @jmx.managed-attribute
248     */

249    public void setRMIClientSocketFactoryBean(final RMIClientSocketFactory JavaDoc bean)
250    {
251       clientSocketFactory = bean;
252    }
253
254    /**
255     * @jmx.managed-attribute
256     */

257    public RMIClientSocketFactory JavaDoc getRMIClientSocketFactoryBean()
258    {
259       return clientSocketFactory;
260    }
261    
262    /**
263     * @jmx.managed-attribute
264     */

265    public void setRMIServerSocketFactory(final String JavaDoc name)
266    {
267       serverSocketFactoryName = name;
268    }
269
270    /**
271     * @jmx.managed-attribute
272     */

273    public String JavaDoc getRMIServerSocketFactory()
274    {
275       return serverSocketFactoryName;
276    }
277
278    /**
279     * @jmx.managed-attribute
280     */

281    public void setRMIServerSocketFactoryBean(final RMIServerSocketFactory JavaDoc bean)
282    {
283       serverSocketFactory = bean;
284    }
285
286    /**
287     * @jmx.managed-attribute
288     */

289    public RMIServerSocketFactory JavaDoc getRMIServerSocketFactoryBean()
290    {
291       return serverSocketFactory;
292    }
293
294    /**
295     * @jmx.managed-attribute
296     */

297    public void setServerAddress(final String JavaDoc address)
298    {
299       serverAddress = address;
300    }
301
302    /**
303     * @jmx.managed-attribute
304     */

305    public String JavaDoc getServerAddress()
306    {
307       return serverAddress;
308    }
309
310    /**
311     * @jmx.managed-attribute
312     */

313    public void setSecurityDomain(String JavaDoc domainName)
314    {
315       this.sslDomain = domainName;
316    }
317
318    /**
319     * @jmx.managed-attribute
320     */

321    public String JavaDoc getSecurityDomain()
322    {
323       return sslDomain;
324    }
325
326    public Serializable JavaDoc getStub()
327    {
328       return this.invokerStub;
329    }
330
331    protected void startService() throws Exception JavaDoc
332    {
333       loadCustomSocketFactories();
334
335       log.debug("RMI Port='" +
336             (rmiPort == ANONYMOUS_PORT ? "Anonymous" :
337             Integer.toString(rmiPort)) + "'");
338
339       log.debug("Client SocketFactory='" +
340             (clientSocketFactory == null ? "Default" :
341             clientSocketFactory.toString()) + "'");
342
343       log.debug("Server SocketFactory='" +
344             (serverSocketFactory == null ? "Default" :
345             serverSocketFactory.toString()) + "'");
346
347       log.debug("Server SocketAddr='" +
348             (serverAddress == null ? "Default" :
349             serverAddress) + "'");
350       log.debug("SecurityDomain='" +
351             (sslDomain == null ? "Default" :
352             sslDomain) + "'");
353
354       InitialContext JavaDoc ctx = new InitialContext JavaDoc();
355
356       // FIXME marcf: This should not be here
357
// and the transaction propagation context importer
358
tpcImporter = TransactionPropagationContextUtil.getTPCImporter();
359
360
361       // Set the transaction manager and transaction propagation
362
// context factory of the GenericProxy class
363

364       Invoker delegateInvoker = createDelegateInvoker();
365
366       // Make the remote invoker proxy available for use by the proxy factory
367
Registry.bind(support.getServiceName(), delegateInvoker);
368
369       // Export CI
370
exportCI();
371
372       log.debug("Bound JRMP invoker for JMX node");
373
374       ctx.close();
375    }
376
377    protected void stopService() throws Exception JavaDoc
378    {
379       InitialContext JavaDoc ctx = new InitialContext JavaDoc();
380
381       try
382       {
383          unexportCI();
384       }
385       finally
386       {
387          ctx.close();
388       }
389       this.clientSocketFactory = null;
390       this.serverSocketFactory = null;
391       this.invokerStub = null;
392    }
393
394    protected void destroyService() throws Exception JavaDoc
395    {
396       // Export references to the bean
397
Registry.unbind(support.getServiceName());
398    }
399
400    /**
401     * Invoke a Remote interface method.
402     */

403    public Object JavaDoc invoke(Invocation invocation)
404       throws Exception JavaDoc
405    {
406       ClassLoader JavaDoc oldCl = TCLAction.UTIL.getContextClassLoader();
407       ObjectName JavaDoc mbean = null;
408       try
409       {
410          // Deserialize the transaction if it is there
411
MarshalledInvocation mi = (MarshalledInvocation) invocation;
412          invocation.setTransaction(importTPC(mi.getTransactionPropagationContext()));
413
414          mbean = (ObjectName JavaDoc) Registry.lookup(invocation.getObjectName());
415
416          // The cl on the thread should be set in another interceptor
417
Object JavaDoc obj = serverAction.invoke(mbean,
418             "invoke",
419             new Object JavaDoc[]{invocation},
420             Invocation.INVOKE_SIGNATURE);
421          return new MarshalledObject JavaDoc(obj);
422       }
423       catch (Exception JavaDoc e)
424       {
425          Throwable JavaDoc th = JMXExceptionDecoder.decode(e);
426          if (log.isTraceEnabled())
427             log.trace("Failed to invoke on mbean: " + mbean, th);
428
429          if (th instanceof Exception JavaDoc)
430             e = (Exception JavaDoc) th;
431
432          throw e;
433       }
434       finally
435       {
436          TCLAction.UTIL.setContextClassLoader(oldCl);
437          Thread.interrupted(); // clear interruption because this thread may be pooled.
438
}
439    }
440
441    protected Invoker createDelegateInvoker()
442    {
443       return new JRMPInvokerProxy(this);
444    }
445
446    protected void exportCI() throws Exception JavaDoc
447    {
448       this.invokerStub = (RemoteStub JavaDoc) UnicastRemoteObject.exportObject
449          (this, rmiPort, clientSocketFactory, serverSocketFactory);
450    }
451
452    protected void unexportCI() throws Exception JavaDoc
453    {
454       UnicastRemoteObject.unexportObject(this, true);
455    }
456
457    protected void rebind(Context JavaDoc ctx, String JavaDoc name, Object JavaDoc val)
458       throws NamingException JavaDoc
459    {
460       // Bind val to name in ctx, and make sure that all
461
// intermediate contexts exist
462

463       Name JavaDoc n = ctx.getNameParser("").parse(name);
464       while (n.size() > 1)
465       {
466          String JavaDoc ctxName = n.get(0);
467          try
468          {
469             ctx = (Context JavaDoc) ctx.lookup(ctxName);
470          }
471          catch (NameNotFoundException JavaDoc e)
472          {
473             ctx = ctx.createSubcontext(ctxName);
474          }
475          n = n.getSuffix(1);
476       }
477
478       ctx.rebind(n.get(0), val);
479    }
480
481    /**
482     * Load and instantiate the clientSocketFactory, serverSocketFactory using
483     * the TCL and set the bind address and SSL domain if the serverSocketFactory
484     * supports it.
485     */

486    protected void loadCustomSocketFactories()
487    {
488       ClassLoader JavaDoc loader = TCLAction.UTIL.getContextClassLoader();
489
490       if( clientSocketFactory == null )
491       {
492          try
493          {
494             if (clientSocketFactoryName != null)
495             {
496                Class JavaDoc csfClass = loader.loadClass(clientSocketFactoryName);
497                clientSocketFactory = (RMIClientSocketFactory JavaDoc) csfClass.newInstance();
498             }
499          }
500          catch (Exception JavaDoc e)
501          {
502             log.error("Failed to load client socket factory", e);
503             clientSocketFactory = null;
504          }
505       }
506
507       if( serverSocketFactory == null )
508       {
509          try
510          {
511             if (serverSocketFactoryName != null)
512             {
513                Class JavaDoc ssfClass = loader.loadClass(serverSocketFactoryName);
514                serverSocketFactory = (RMIServerSocketFactory JavaDoc) ssfClass.newInstance();
515                if (serverAddress != null)
516                {
517                   // See if the server socket supports setBindAddress(String)
518
try
519                   {
520                      Class JavaDoc[] parameterTypes = {String JavaDoc.class};
521                      Method JavaDoc m = ssfClass.getMethod("setBindAddress", parameterTypes);
522                      Object JavaDoc[] args = {serverAddress};
523                      m.invoke(serverSocketFactory, args);
524                   }
525                   catch (NoSuchMethodException JavaDoc e)
526                   {
527                      log.warn("Socket factory does not support setBindAddress(String)");
528                      // Go with default address
529
}
530                   catch (Exception JavaDoc e)
531                   {
532                      log.warn("Failed to setBindAddress=" + serverAddress + " on socket factory", e);
533                      // Go with default address
534
}
535                }
536                /* See if the server socket supports setSecurityDomain(SecurityDomain)
537                if an sslDomain was specified
538                */

539                if (sslDomain != null)
540                {
541                   try
542                   {
543                      InitialContext JavaDoc ctx = new InitialContext JavaDoc();
544                      SecurityDomain domain = (SecurityDomain) ctx.lookup(sslDomain);
545                      Class JavaDoc[] parameterTypes = {SecurityDomain.class};
546                      Method JavaDoc m = ssfClass.getMethod("setSecurityDomain", parameterTypes);
547                      Object JavaDoc[] args = {domain};
548                      m.invoke(serverSocketFactory, args);
549                   }
550                   catch (NoSuchMethodException JavaDoc e)
551                   {
552                      log.error("Socket factory does not support setSecurityDomain(SecurityDomain)");
553                   }
554                   catch (Exception JavaDoc e)
555                   {
556                      log.error("Failed to setSecurityDomain=" + sslDomain + " on socket factory", e);
557                   }
558                }
559             }
560             // If a bind address was specified create a DefaultSocketFactory
561
else if (serverAddress != null)
562             {
563                DefaultSocketFactory defaultFactory = new DefaultSocketFactory(backlog);
564                serverSocketFactory = defaultFactory;
565                try
566                {
567                   defaultFactory.setBindAddress(serverAddress);
568                }
569                catch (UnknownHostException JavaDoc e)
570                {
571                   log.error("Failed to setBindAddress=" + serverAddress + " on socket factory", e);
572                }
573             }
574          }
575          catch (Exception JavaDoc e)
576          {
577             log.error("operation failed", e);
578             serverSocketFactory = null;
579          }
580       }
581    }
582
583    /**
584     * Import a transaction propagation context into the local VM, and
585     * return the corresponding <code>Transaction</code>.
586     *
587     * @return A transaction or null if no tpc.
588     */

589    protected Transaction JavaDoc importTPC(Object JavaDoc tpc)
590    {
591       if (tpc != null)
592          return tpcImporter.importTransactionPropagationContext(tpc);
593       return null;
594    }
595
596    //
597
// Delegate the ServiceMBean details to our support delegate
598
//
599

600    public String JavaDoc getName()
601    {
602       return support.getName();
603    }
604
605    public MBeanServer JavaDoc getServer()
606    {
607       return support.getServer();
608    }
609
610    public int getState()
611    {
612       return support.getState();
613    }
614
615    public String JavaDoc getStateString()
616    {
617       return support.getStateString();
618    }
619
620    public void create() throws Exception JavaDoc
621    {
622       support.create();
623    }
624
625    public void start() throws Exception JavaDoc
626    {
627       support.start();
628    }
629
630    public void stop()
631    {
632       support.stop();
633    }
634
635    public void destroy()
636    {
637       support.destroy();
638    }
639
640    public void jbossInternalLifecycle(String JavaDoc method) throws Exception JavaDoc
641    {
642       support.jbossInternalLifecycle(method);
643    }
644
645    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name)
646       throws Exception JavaDoc
647    {
648       return support.preRegister(server, name);
649    }
650
651    public void postRegister(Boolean JavaDoc registrationDone)
652    {
653       support.postRegister(registrationDone);
654    }
655
656    public void preDeregister() throws Exception JavaDoc
657    {
658       support.preDeregister();
659    }
660
661    public void postDeregister()
662    {
663       support.postDeregister();
664    }
665
666    interface TCLAction
667    {
668       class UTIL
669       {
670          static TCLAction getTCLAction()
671          {
672             return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
673          }
674
675          static ClassLoader JavaDoc getContextClassLoader()
676          {
677             return getTCLAction().getContextClassLoader();
678          }
679
680          static ClassLoader JavaDoc getContextClassLoader(Thread JavaDoc thread)
681          {
682             return getTCLAction().getContextClassLoader(thread);
683          }
684
685          static void setContextClassLoader(ClassLoader JavaDoc cl)
686          {
687             getTCLAction().setContextClassLoader(cl);
688          }
689
690          static void setContextClassLoader(Thread JavaDoc thread, ClassLoader JavaDoc cl)
691          {
692             getTCLAction().setContextClassLoader(thread, cl);
693          }
694       }
695
696       TCLAction NON_PRIVILEGED = new TCLAction()
697       {
698          public ClassLoader JavaDoc getContextClassLoader()
699          {
700             return Thread.currentThread().getContextClassLoader();
701          }
702
703          public ClassLoader JavaDoc getContextClassLoader(Thread JavaDoc thread)
704          {
705             return thread.getContextClassLoader();
706          }
707
708          public void setContextClassLoader(ClassLoader JavaDoc cl)
709          {
710             Thread.currentThread().setContextClassLoader(cl);
711          }
712
713          public void setContextClassLoader(Thread JavaDoc thread, ClassLoader JavaDoc cl)
714          {
715             thread.setContextClassLoader(cl);
716          }
717       };
718
719       TCLAction PRIVILEGED = new TCLAction()
720       {
721          private final PrivilegedAction JavaDoc getTCLPrivilegedAction = new PrivilegedAction JavaDoc()
722          {
723             public Object JavaDoc run()
724             {
725                return Thread.currentThread().getContextClassLoader();
726             }
727          };
728
729          public ClassLoader JavaDoc getContextClassLoader()
730          {
731             return (ClassLoader JavaDoc) AccessController.doPrivileged(getTCLPrivilegedAction);
732          }
733
734          public ClassLoader JavaDoc getContextClassLoader(final Thread JavaDoc thread)
735          {
736             return (ClassLoader JavaDoc) AccessController.doPrivileged(new PrivilegedAction JavaDoc()
737             {
738                public Object JavaDoc run()
739                {
740                   return thread.getContextClassLoader();
741                }
742             });
743          }
744
745          public void setContextClassLoader(final ClassLoader JavaDoc cl)
746          {
747             AccessController.doPrivileged(new PrivilegedAction JavaDoc()
748             {
749                public Object JavaDoc run()
750                {
751                   Thread.currentThread().setContextClassLoader(cl);
752                   return null;
753                }
754             });
755          }
756
757          public void setContextClassLoader(final Thread JavaDoc thread, final ClassLoader JavaDoc cl)
758          {
759             AccessController.doPrivileged(new PrivilegedAction JavaDoc()
760             {
761                public Object JavaDoc run()
762                {
763                   thread.setContextClassLoader(cl);
764                   return null;
765                }
766             });
767          }
768       };
769
770       ClassLoader JavaDoc getContextClassLoader();
771
772       ClassLoader JavaDoc getContextClassLoader(Thread JavaDoc thread);
773
774       void setContextClassLoader(ClassLoader JavaDoc cl);
775
776       void setContextClassLoader(Thread JavaDoc thread, ClassLoader JavaDoc cl);
777    }
778
779    /**
780     * Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
781     * running with a security manager.
782     */

783    class MBeanServerAction implements PrivilegedExceptionAction JavaDoc
784    {
785       private ObjectName JavaDoc target;
786       String JavaDoc method;
787       Object JavaDoc[] args;
788       String JavaDoc[] sig;
789
790       MBeanServerAction()
791       {
792       }
793
794       MBeanServerAction(ObjectName JavaDoc target, String JavaDoc method, Object JavaDoc[] args, String JavaDoc[] sig)
795       {
796          this.target = target;
797          this.method = method;
798          this.args = args;
799          this.sig = sig;
800       }
801
802       public Object JavaDoc run() throws Exception JavaDoc
803       {
804          Object JavaDoc rtnValue = support.getServer().invoke(target, method, args, sig);
805          return rtnValue;
806       }
807
808       Object JavaDoc invoke(ObjectName JavaDoc target, String JavaDoc method, Object JavaDoc[] args, String JavaDoc[] sig)
809          throws Exception JavaDoc
810       {
811          SecurityManager JavaDoc sm = System.getSecurityManager();
812          Object JavaDoc rtnValue = null;
813          if (sm == null)
814          {
815             // Direct invocation on MBeanServer
816
rtnValue = support.getServer().invoke(target, method, args, sig);
817          }
818          else
819          {
820             try
821             {
822                // Encapsulate the invocation in a PrivilegedExceptionAction
823
MBeanServerAction action = new MBeanServerAction(target, method, args, sig);
824                rtnValue = AccessController.doPrivileged(action);
825             }
826             catch (PrivilegedActionException JavaDoc e)
827             {
828                Exception JavaDoc ex = e.getException();
829                throw ex;
830             }
831          }
832          return rtnValue;
833       }
834    }
835 }
836
Popular Tags