Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.invocation.jrmp » server » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source.
    3    * Copyright 2006, Red Hat Middleware LLC, and individual contributors
    4    * as indicated by the @author tags. See the copyright.txt file in the
    5    * distribution for a 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;
   25   import java.net.InetAddress;
   26   import java.net.UnknownHostException;
   27   import java.io.Serializable;
   28   import java.rmi.server.RemoteServer;
   29   import java.rmi.server.UnicastRemoteObject;
   30   import java.rmi.server.RMIServerSocketFactory;
   31   import java.rmi.server.RMIClientSocketFactory;
   32   import java.rmi.server.RemoteStub;
   33   import java.rmi.MarshalledObject;
   34   import java.security.PrivilegedAction;
   35   import java.security.AccessController;
   36   import java.security.PrivilegedExceptionAction;
   37   import java.security.PrivilegedActionException;
   38   
   39   import javax.management.ObjectName;
   40   import javax.management.MBeanRegistration;
   41   import javax.management.MBeanServer;
   42   import javax.naming.Name;
   43   import javax.naming.InitialContext;
   44   import javax.naming.Context;
   45   import javax.naming.NamingException;
   46   import javax.naming.NameNotFoundException;
   47   import javax.transaction.Transaction;
   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.TransactionPropagationContextUtil;
   61   
   62   /**
   63    * The JRMPInvoker is an RMI implementation that can generate Invocations
   64    * from RMI/JRMP into the JMX base.
   65    *
   66    * @author <a href="mailto:marc.fleury@jboss.org>Marc Fleury</a>
   67    * @author <a href="mailto:scott.stark@jboss.org>Scott Stark</a>
   68    * @version $Revision: 60886 $
   69    * @jmx.mbean extends="org.jboss.system.ServiceMBean"
   70    */
   71   public class JRMPInvoker
   72      extends RemoteServer
   73      implements Invoker, JRMPInvokerMBean, MBeanRegistration
   74   {
   75      /** @since 4.2.0 */
   76      static final long serialVersionUID = 3110972460891691492L;
   77      
   78      /**
   79       * Identifer to instruct the usage of an anonymous port.
   80       */
   81      public static final int ANONYMOUS_PORT = 0;
   82   
   83      /**
   84       * Instance logger.
   85       */
   86      protected Logger log;
   87   
   88      /**
   89       * Service MBean support delegate.
   90       */
   91      protected ServiceMBeanSupport support;
   92   
   93      /**
   94       * The port the container will be exported on
   95       */
   96      protected int rmiPort = ANONYMOUS_PORT;
   97   
   98      /**
   99       * An optional custom client socket factory
  100       */
  101      protected RMIClientSocketFactory clientSocketFactory;
  102   
  103      /**
  104       * An optional custom server socket factory
  105       */
  106      protected RMIServerSocketFactory serverSocketFactory;
  107   
  108      /**
  109       * The class name of the optional custom client socket factory
  110       */
  111      protected String clientSocketFactoryName;
  112   
  113      /**
  114       * The class name of the optional custom server socket factory
  115       */
  116      protected String serverSocketFactoryName;
  117   
  118      /**
  119       * The address to bind the rmi port on
  120       */
  121      protected String serverAddress;
  122      /**
  123       * The name of the security domain to use with server sockets that support SSL
  124       */
  125      protected String sslDomain;
  126   
  127      protected RemoteStub invokerStub;
  128      /**
  129       * The socket accept backlog
  130       */
  131      protected int backlog = 200;
  132      /**
  133       * A flag to enable caching of classes in the MarshalledValueInputStream
  134       */
  135      protected boolean enableClassCaching = false;
  136      /**
  137       * A priviledged actions for MBeanServer.invoke when running with sec mgr
  138       */
  139      private MBeanServerAction serverAction = new MBeanServerAction();
  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
  149            {
  150               delegate.startService();
  151            }
  152            protected void stopService() throws Exception
  153            {
  154               delegate.stopService();
  155            }
  156            protected void destroyService() throws Exception
  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 getServerHostName()
  203      {
  204         try
  205         {
  206            return InetAddress.getLocalHost().getHostName();
  207         }
  208         catch (Exception 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 name)
  234      {
  235         clientSocketFactoryName = name;
  236      }
  237   
  238      /**
  239       * @jmx.managed-attribute
  240       */
  241      public String getRMIClientSocketFactory()
  242      {
  243         return clientSocketFactoryName;
  244      }
  245   
  246      /**
  247       * @jmx.managed-attribute
  248       */
  249      public void setRMIClientSocketFactoryBean(final RMIClientSocketFactory bean)
  250      {
  251         clientSocketFactory = bean;
  252      }
  253   
  254      /**
  255       * @jmx.managed-attribute
  256       */
  257      public RMIClientSocketFactory getRMIClientSocketFactoryBean()
  258      {
  259         return clientSocketFactory;
  260      }
  261      
  262      /**
  263       * @jmx.managed-attribute
  264       */
  265      public void setRMIServerSocketFactory(final String name)
  266      {
  267         serverSocketFactoryName = name;
  268      }
  269   
  270      /**
  271       * @jmx.managed-attribute
  272       */
  273      public String getRMIServerSocketFactory()
  274      {
  275         return serverSocketFactoryName;
  276      }
  277   
  278      /**
  279       * @jmx.managed-attribute
  280       */
  281      public void setRMIServerSocketFactoryBean(final RMIServerSocketFactory bean)
  282      {
  283         serverSocketFactory = bean;
  284      }
  285   
  286      /**
  287       * @jmx.managed-attribute
  288       */
  289      public RMIServerSocketFactory getRMIServerSocketFactoryBean()
  290      {
  291         return serverSocketFactory;
  292      }
  293   
  294      /**
  295       * @jmx.managed-attribute
  296       */
  297      public void setServerAddress(final String address)
  298      {
  299         serverAddress = address;
  300      }
  301   
  302      /**
  303       * @jmx.managed-attribute
  304       */
  305      public String getServerAddress()
  306      {
  307         return serverAddress;
  308      }
  309   
  310      /**
  311       * @jmx.managed-attribute
  312       */
  313      public void setSecurityDomain(String domainName)
  314      {
  315         this.sslDomain = domainName;
  316      }
  317   
  318      /**
  319       * @jmx.managed-attribute
  320       */
  321      public String getSecurityDomain()
  322      {
  323         return sslDomain;
  324      }
  325   
  326      public Serializable getStub()
  327      {
  328         return this.invokerStub;
  329      }
  330   
  331      protected void startService() throws Exception
  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 ctx = new InitialContext();
  355   
  356         // Validate that there is a TransactionPropagationContextImporter
  357         // bound in JNDI
  358         TransactionPropagationContextUtil.getTPCImporter();
  359   
  360         // Set the transaction manager and transaction propagation
  361         // context factory of the GenericProxy class
  362   
  363         Invoker delegateInvoker = createDelegateInvoker();
  364   
  365         // Make the remote invoker proxy available for use by the proxy factory
  366         Registry.bind(support.getServiceName(), delegateInvoker);
  367   
  368         // Export CI
  369         exportCI();
  370   
  371         log.debug("Bound JRMP invoker for JMX node");
  372   
  373         ctx.close();
  374      }
  375   
  376      protected void stopService() throws Exception
  377      {
  378         InitialContext ctx = new InitialContext();
  379   
  380         try
  381         {
  382            unexportCI();
  383         }
  384         finally
  385         {
  386            ctx.close();
  387         }
  388         this.clientSocketFactory = null;
  389         this.serverSocketFactory = null;
  390         this.invokerStub = null;
  391      }
  392   
  393      protected void destroyService() throws Exception
  394      {
  395         // Export references to the bean
  396         Registry.unbind(support.getServiceName());
  397      }
  398   
  399      /**
  400       * Invoke a Remote interface method.
  401       */
  402      public Object invoke(Invocation invocation)
  403         throws Exception
  404      {
  405         ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader();
  406         ObjectName mbean = null;
  407         try
  408         {
  409            // Deserialize the transaction if it is there
  410            MarshalledInvocation mi = (MarshalledInvocation) invocation;
  411            invocation.setTransaction(importTPC(mi.getTransactionPropagationContext()));
  412   
  413            mbean = (ObjectName) Registry.lookup(invocation.getObjectName());
  414   
  415            // The cl on the thread should be set in another interceptor
  416            Object obj = serverAction.invoke(mbean,
  417               "invoke",
  418               new Object[]{invocation},
  419               Invocation.INVOKE_SIGNATURE);
  420            return new MarshalledObject(obj);
  421         }
  422         catch (Exception e)
  423         {
  424            Throwable th = JMXExceptionDecoder.decode(e);
  425            if (log.isTraceEnabled())
  426               log.trace("Failed to invoke on mbean: " + mbean, th);
  427   
  428            if (th instanceof Exception)
  429               e = (Exception) th;
  430   
  431            throw e;
  432         }
  433         finally
  434         {
  435            TCLAction.UTIL.setContextClassLoader(oldCl);
  436            Thread.interrupted(); // clear interruption because this thread may be pooled.
  437         }
  438      }
  439   
  440      protected Invoker createDelegateInvoker()
  441      {
  442         return new JRMPInvokerProxy(this);
  443      }
  444   
  445      protected void exportCI() throws Exception
  446      {
  447         this.invokerStub = (RemoteStub) UnicastRemoteObject.exportObject
  448            (this, rmiPort, clientSocketFactory, serverSocketFactory);
  449      }
  450   
  451      protected void unexportCI() throws Exception
  452      {
  453         UnicastRemoteObject.unexportObject(this, true);
  454      }
  455   
  456      protected void rebind(Context ctx, String name, Object val)
  457         throws NamingException
  458      {
  459         // Bind val to name in ctx, and make sure that all
  460         // intermediate contexts exist
  461   
  462         Name n = ctx.getNameParser("").parse(name);
  463         while (n.size() > 1)
  464         {
  465            String ctxName = n.get(0);
  466            try
  467            {
  468               ctx = (Context) ctx.lookup(ctxName);
  469            }
  470            catch (NameNotFoundException e)
  471            {
  472               ctx = ctx.createSubcontext(ctxName);
  473            }
  474            n = n.getSuffix(1);
  475         }
  476   
  477         ctx.rebind(n.get(0), val);
  478      }
  479   
  480      /**
  481       * Load and instantiate the clientSocketFactory, serverSocketFactory using
  482       * the TCL and set the bind address and SSL domain if the serverSocketFactory
  483       * supports it.
  484       */
  485      protected void loadCustomSocketFactories()
  486      {
  487         ClassLoader loader = TCLAction.UTIL.getContextClassLoader();
  488   
  489         if( clientSocketFactory == null )
  490         {
  491            try
  492            {
  493               if (clientSocketFactoryName != null)
  494               {
  495                  Class csfClass = loader.loadClass(clientSocketFactoryName);
  496                  clientSocketFactory = (RMIClientSocketFactory) csfClass.newInstance();
  497               }
  498            }
  499            catch (Exception e)
  500            {
  501               log.error("Failed to load client socket factory", e);
  502               clientSocketFactory = null;
  503            }
  504         }
  505   
  506         if( serverSocketFactory == null )
  507         {
  508            try
  509            {
  510               if (serverSocketFactoryName != null)
  511               {
  512                  Class ssfClass = loader.loadClass(serverSocketFactoryName);
  513                  serverSocketFactory = (RMIServerSocketFactory) ssfClass.newInstance();
  514                  if (serverAddress != null)
  515                  {
  516                     // See if the server socket supports setBindAddress(String)
  517                     try
  518                     {
  519                        Class[] parameterTypes = {String.class};
  520                        Method m = ssfClass.getMethod("setBindAddress", parameterTypes);
  521                        Object[] args = {serverAddress};
  522                        m.invoke(serverSocketFactory, args);
  523                     }
  524                     catch (NoSuchMethodException e)
  525                     {
  526                        log.warn("Socket factory does not support setBindAddress(String)");
  527                        // Go with default address
  528                     }
  529                     catch (Exception e)
  530                     {
  531                        log.warn("Failed to setBindAddress=" + serverAddress + " on socket factory", e);
  532                        // Go with default address
  533                     }
  534                  }
  535                  /* See if the server socket supports setSecurityDomain(SecurityDomain)
  536                  if an sslDomain was specified
  537                  */
  538                  if (sslDomain != null)
  539                  {
  540                     try
  541                     {
  542                        InitialContext ctx = new InitialContext();
  543                        SecurityDomain domain = (SecurityDomain) ctx.lookup(sslDomain);
  544                        Class[] parameterTypes = {SecurityDomain.class};
  545                        Method m = ssfClass.getMethod("setSecurityDomain", parameterTypes);
  546                        Object[] args = {domain};
  547                        m.invoke(serverSocketFactory, args);
  548                     }
  549                     catch (NoSuchMethodException e)
  550                     {
  551                        log.error("Socket factory does not support setSecurityDomain(SecurityDomain)");
  552                     }
  553                     catch (Exception e)
  554                     {
  555                        log.error("Failed to setSecurityDomain=" + sslDomain + " on socket factory", e);
  556                     }
  557                  }
  558               }
  559               // If a bind address was specified create a DefaultSocketFactory
  560               else if (serverAddress != null)
  561               {
  562                  DefaultSocketFactory defaultFactory = new DefaultSocketFactory(backlog);
  563                  serverSocketFactory = defaultFactory;
  564                  try
  565                  {
  566                     defaultFactory.setBindAddress(serverAddress);
  567                  }
  568                  catch (UnknownHostException e)
  569                  {
  570                     log.error("Failed to setBindAddress=" + serverAddress + " on socket factory", e);
  571                  }
  572               }
  573            }
  574            catch (Exception e)
  575            {
  576               log.error("operation failed", e);
  577               serverSocketFactory = null;
  578            }
  579         }
  580      }
  581   
  582      /**
  583       * Import a transaction propagation context into the local VM, and
  584       * return the corresponding <code>Transaction</code>.
  585       *
  586       * @return A transaction or null if no tpc.
  587       */
  588      protected Transaction importTPC(Object tpc)
  589      {
  590         if (tpc != null)
  591            return TransactionPropagationContextUtil.importTPC(tpc);
  592         return null;
  593      }
  594   
  595      //
  596      // Delegate the ServiceMBean details to our support delegate
  597      //
  598   
  599      public String getName()
  600      {
  601         return support.getName();
  602      }
  603   
  604      public MBeanServer getServer()
  605      {
  606         return support.getServer();
  607      }
  608   
  609      public int getState()
  610      {
  611         return support.getState();
  612      }
  613   
  614      public String getStateString()
  615      {
  616         return support.getStateString();
  617      }
  618   
  619      public void create() throws Exception
  620      {
  621         support.create();
  622      }
  623   
  624      public void start() throws Exception
  625      {
  626         support.start();
  627      }
  628   
  629      public void stop()
  630      {
  631         support.stop();
  632      }
  633   
  634      public void destroy()
  635      {
  636         support.destroy();
  637      }
  638   
  639      public void jbossInternalLifecycle(String method) throws Exception
  640      {
  641         support.jbossInternalLifecycle(method);
  642      }
  643   
  644      public ObjectName preRegister(MBeanServer server, ObjectName name)
  645         throws Exception
  646      {
  647         return support.preRegister(server, name);
  648      }
  649   
  650      public void postRegister(Boolean registrationDone)
  651      {
  652         support.postRegister(registrationDone);
  653      }
  654   
  655      public void preDeregister() throws Exception
  656      {
  657         support.preDeregister();
  658      }
  659   
  660      public void postDeregister()
  661      {
  662         support.postDeregister();
  663      }
  664   
  665      interface TCLAction
  666      {
  667         class UTIL
  668         {
  669            static TCLAction getTCLAction()
  670            {
  671               return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
  672            }
  673   
  674            static ClassLoader getContextClassLoader()
  675            {
  676               return getTCLAction().getContextClassLoader();
  677            }
  678   
  679            static ClassLoader getContextClassLoader(Thread thread)
  680            {
  681               return getTCLAction().getContextClassLoader(thread);
  682            }
  683   
  684            static void setContextClassLoader(ClassLoader cl)
  685            {
  686               getTCLAction().setContextClassLoader(cl);
  687            }
  688   
  689            static void setContextClassLoader(Thread thread, ClassLoader cl)
  690            {
  691               getTCLAction().setContextClassLoader(thread, cl);
  692            }
  693         }
  694   
  695         TCLAction NON_PRIVILEGED = new TCLAction()
  696         {
  697            public ClassLoader getContextClassLoader()
  698            {
  699               return Thread.currentThread().getContextClassLoader();
  700            }
  701   
  702            public ClassLoader getContextClassLoader(Thread thread)
  703            {
  704               return thread.getContextClassLoader();
  705            }
  706   
  707            public void setContextClassLoader(ClassLoader cl)
  708            {
  709               Thread.currentThread().setContextClassLoader(cl);
  710            }
  711   
  712            public void setContextClassLoader(Thread thread, ClassLoader cl)
  713            {
  714               thread.setContextClassLoader(cl);
  715            }
  716         };
  717   
  718         TCLAction PRIVILEGED = new TCLAction()
  719         {
  720            private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction()
  721            {
  722               public Object run()
  723               {
  724                  return Thread.currentThread().getContextClassLoader();
  725               }
  726            };
  727   
  728            public ClassLoader getContextClassLoader()
  729            {
  730               return (ClassLoader) AccessController.doPrivileged(getTCLPrivilegedAction);
  731            }
  732   
  733            public ClassLoader getContextClassLoader(final Thread thread)
  734            {
  735               return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction()
  736               {
  737                  public Object run()
  738                  {
  739                     return thread.getContextClassLoader();
  740                  }
  741               });
  742            }
  743   
  744            public void setContextClassLoader(final ClassLoader cl)
  745            {
  746               AccessController.doPrivileged(new PrivilegedAction()
  747               {
  748                  public Object run()
  749                  {
  750                     Thread.currentThread().setContextClassLoader(cl);
  751                     return null;
  752                  }
  753               });
  754            }
  755   
  756            public void setContextClassLoader(final Thread thread, final ClassLoader cl)
  757            {
  758               AccessController.doPrivileged(new PrivilegedAction()
  759               {
  760                  public Object run()
  761                  {
  762                     thread.setContextClassLoader(cl);
  763                     return null;
  764                  }
  765               });
  766            }
  767         };
  768   
  769         ClassLoader getContextClassLoader();
  770   
  771         ClassLoader getContextClassLoader(Thread thread);
  772   
  773         void setContextClassLoader(ClassLoader cl);
  774   
  775         void setContextClassLoader(Thread thread, ClassLoader cl);
  776      }
  777   
  778      /**
  779       * Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
  780       * running with a security manager.
  781       */
  782      class MBeanServerAction implements PrivilegedExceptionAction
  783      {
  784         private ObjectName target;
  785         String method;
  786         Object[] args;
  787         String[] sig;
  788   
  789         MBeanServerAction()
  790         {
  791         }
  792   
  793         MBeanServerAction(ObjectName target, String method, Object[] args, String[] sig)
  794         {
  795            this.target = target;
  796            this.method = method;
  797            this.args = args;
  798            this.sig = sig;
  799         }
  800   
  801         public Object run() throws Exception
  802         {
  803            Object rtnValue = support.getServer().invoke(target, method, args, sig);
  804            return rtnValue;
  805         }
  806   
  807         Object invoke(ObjectName target, String method, Object[] args, String[] sig)
  808            throws Exception
  809         {
  810            SecurityManager sm = System.getSecurityManager();
  811            Object rtnValue = null;
  812            if (sm == null)
  813            {
  814               // Direct invocation on MBeanServer
  815               rtnValue = support.getServer().invoke(target, method, args, sig);
  816            }
  817            else
  818            {
  819               try
  820               {
  821                  // Encapsulate the invocation in a PrivilegedExceptionAction
  822                  MBeanServerAction action = new MBeanServerAction(target, method, args, sig);
  823                  rtnValue = AccessController.doPrivileged(action);
  824               }
  825               catch (PrivilegedActionException e)
  826               {
  827                  Exception ex = e.getException();
  828                  throw ex;
  829               }
  830            }
  831            return rtnValue;
  832         }
  833      }
  834   }

Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.invocation.jrmp » server » [javadoc | source]