/projects/jboss-5.1.0/server/src/main/org/jboss/invocation/jrmp/server/JRMPInvoker.java
https://gitlab.com/essere.lab.public/qualitas.class-corpus · Java · 874 lines · 593 code · 111 blank · 170 comment · 28 complexity · 276acdf942522f38b8615baf0f0b7dd2 MD5 · raw file
- /*
- * JBoss, Home of Professional Open Source.
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
- package org.jboss.invocation.jrmp.server;
- import java.lang.reflect.Method;
- import java.net.InetAddress;
- import java.net.UnknownHostException;
- import java.io.Serializable;
- import java.rmi.server.RemoteServer;
- import java.rmi.server.UnicastRemoteObject;
- import java.rmi.server.RMIServerSocketFactory;
- import java.rmi.server.RMIClientSocketFactory;
- import java.rmi.server.RemoteStub;
- import java.rmi.MarshalledObject;
- import java.security.PrivilegedAction;
- import java.security.AccessController;
- import java.security.PrivilegedExceptionAction;
- import java.security.PrivilegedActionException;
- import javax.management.ObjectName;
- import javax.management.MBeanRegistration;
- import javax.management.MBeanServer;
- import javax.naming.Name;
- import javax.naming.InitialContext;
- import javax.naming.Context;
- import javax.naming.NamingException;
- import javax.naming.NameNotFoundException;
- import javax.transaction.Transaction;
- import org.jboss.beans.metadata.api.annotations.Create;
- import org.jboss.beans.metadata.api.annotations.Destroy;
- import org.jboss.beans.metadata.api.annotations.Start;
- import org.jboss.beans.metadata.api.annotations.Stop;
- import org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy;
- import org.jboss.invocation.Invocation;
- import org.jboss.invocation.Invoker;
- import org.jboss.invocation.MarshalledInvocation;
- import org.jboss.invocation.MarshalledValueInputStream;
- import org.jboss.kernel.spi.dependency.KernelControllerContext;
- import org.jboss.kernel.spi.dependency.KernelControllerContextAware;
- import org.jboss.logging.Logger;
- import org.jboss.mx.util.JMXExceptionDecoder;
- import org.jboss.net.sockets.DefaultSocketFactory;
- import org.jboss.security.SecurityDomain;
- import org.jboss.system.Registry;
- import org.jboss.system.ServiceMBeanSupport;
- import org.jboss.tm.TransactionPropagationContextUtil;
- /**
- * The JRMPInvoker is an RMI implementation that can generate Invocations
- * from RMI/JRMP into the JMX base.
- *
- * @author <a href="mailto:marc.fleury@jboss.org>Marc Fleury</a>
- * @author <a href="mailto:scott.stark@jboss.org>Scott Stark</a>
- * @version $Revision: 79760 $
- * @jmx.mbean extends="org.jboss.system.ServiceMBean"
- */
- public class JRMPInvoker
- extends RemoteServer
- implements Invoker, JRMPInvokerMBean, MBeanRegistration, KernelControllerContextAware
- {
- /** @since 4.2.0 */
- static final long serialVersionUID = 3110972460891691492L;
-
- /**
- * Identifer to instruct the usage of an anonymous port.
- */
- public static final int ANONYMOUS_PORT = 0;
- /**
- * Instance logger.
- */
- protected Logger log;
- /**
- * Service MBean support delegate.
- */
- protected ServiceMBeanSupport support;
- /**
- * The port the container will be exported on
- */
- protected int rmiPort = ANONYMOUS_PORT;
- /**
- * An optional custom client socket factory
- */
- protected RMIClientSocketFactory clientSocketFactory;
- /**
- * An optional custom server socket factory
- */
- protected RMIServerSocketFactory serverSocketFactory;
- /**
- * The class name of the optional custom client socket factory
- */
- protected String clientSocketFactoryName;
- /**
- * The class name of the optional custom server socket factory
- */
- protected String serverSocketFactoryName;
- /**
- * The address to bind the rmi port on
- */
- protected String serverAddress;
- /**
- * The name of the security domain to use with server sockets that support SSL
- */
- protected String sslDomain;
- protected RemoteStub invokerStub;
- /**
- * The socket accept backlog
- */
- protected int backlog = 200;
- /**
- * A flag to enable caching of classes in the MarshalledValueInputStream
- */
- protected boolean enableClassCaching = false;
- /**
- * A priviledged actions for MBeanServer.invoke when running with sec mgr
- */
- private MBeanServerAction serverAction = new MBeanServerAction();
- public JRMPInvoker()
- {
- final JRMPInvoker delegate = this;
- // adapt the support delegate to invoke our state methods
- support = new ServiceMBeanSupport(getClass())
- {
- protected void startService() throws Exception
- {
- delegate.startService();
- }
- protected void stopService() throws Exception
- {
- delegate.stopService();
- }
- protected void destroyService() throws Exception
- {
- delegate.destroyService();
- }
- };
- // Setup logging from delegate
- log = support.getLog();
- }
- /**
- * @jmx.managed-attribute
- */
- public int getBacklog()
- {
- return backlog;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setBacklog(int back)
- {
- backlog = back;
- }
- /**
- * @jmx.managed-attribute
- */
- public boolean getEnableClassCaching()
- {
- return enableClassCaching;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setEnableClassCaching(boolean flag)
- {
- enableClassCaching = flag;
- MarshalledValueInputStream.useClassCache(enableClassCaching);
- }
- /**
- * @return The localhost name or null.
- */
- public String getServerHostName()
- {
- try
- {
- return InetAddress.getLocalHost().getHostName();
- }
- catch (Exception ignored)
- {
- return null;
- }
- }
- /**
- * @jmx.managed-attribute
- */
- public void setRMIObjectPort(final int rmiPort)
- {
- this.rmiPort = rmiPort;
- }
- /**
- * @jmx.managed-attribute
- */
- public int getRMIObjectPort()
- {
- return rmiPort;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setRMIClientSocketFactory(final String name)
- {
- clientSocketFactoryName = name;
- }
- /**
- * @jmx.managed-attribute
- */
- public String getRMIClientSocketFactory()
- {
- return clientSocketFactoryName;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setRMIClientSocketFactoryBean(final RMIClientSocketFactory bean)
- {
- clientSocketFactory = bean;
- }
- /**
- * @jmx.managed-attribute
- */
- public RMIClientSocketFactory getRMIClientSocketFactoryBean()
- {
- return clientSocketFactory;
- }
-
- /**
- * @jmx.managed-attribute
- */
- public void setRMIServerSocketFactory(final String name)
- {
- serverSocketFactoryName = name;
- }
- /**
- * @jmx.managed-attribute
- */
- public String getRMIServerSocketFactory()
- {
- return serverSocketFactoryName;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setRMIServerSocketFactoryBean(final RMIServerSocketFactory bean)
- {
- serverSocketFactory = bean;
- }
- /**
- * @jmx.managed-attribute
- */
- public RMIServerSocketFactory getRMIServerSocketFactoryBean()
- {
- return serverSocketFactory;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setServerAddress(final String address)
- {
- serverAddress = address;
- }
- /**
- * @jmx.managed-attribute
- */
- public String getServerAddress()
- {
- return serverAddress;
- }
- /**
- * @jmx.managed-attribute
- */
- public void setSecurityDomain(String domainName)
- {
- this.sslDomain = domainName;
- }
- /**
- * @jmx.managed-attribute
- */
- public String getSecurityDomain()
- {
- return sslDomain;
- }
- public Serializable getStub()
- {
- return this.invokerStub;
- }
- protected void startService() throws Exception
- {
- loadCustomSocketFactories();
- log.debug("RMI Port='" +
- (rmiPort == ANONYMOUS_PORT ? "Anonymous" :
- Integer.toString(rmiPort)) + "'");
- log.debug("Client SocketFactory='" +
- (clientSocketFactory == null ? "Default" :
- clientSocketFactory.toString()) + "'");
- log.debug("Server SocketFactory='" +
- (serverSocketFactory == null ? "Default" :
- serverSocketFactory.toString()) + "'");
- log.debug("Server SocketAddr='" +
- (serverAddress == null ? "Default" :
- serverAddress) + "'");
- log.debug("SecurityDomain='" +
- (sslDomain == null ? "Default" :
- sslDomain) + "'");
- InitialContext ctx = new InitialContext();
- // Validate that there is a TransactionPropagationContextImporter
- // bound in JNDI
- TransactionPropagationContextUtil.getTPCImporter();
- // Set the transaction manager and transaction propagation
- // context factory of the GenericProxy class
- Invoker delegateInvoker = createDelegateInvoker();
- // Make the remote invoker proxy available for use by the proxy factory
- Registry.bind(support.getServiceName(), delegateInvoker);
- // Export CI
- exportCI();
- log.debug("Bound JRMP invoker for JMX node");
- ctx.close();
- }
- protected void stopService() throws Exception
- {
- InitialContext ctx = new InitialContext();
- try
- {
- unexportCI();
- }
- finally
- {
- ctx.close();
- }
- this.clientSocketFactory = null;
- this.serverSocketFactory = null;
- this.invokerStub = null;
- }
- protected void destroyService() throws Exception
- {
- // Export references to the bean
- Registry.unbind(support.getServiceName());
- }
- /**
- * Invoke a Remote interface method.
- */
- public Object invoke(Invocation invocation)
- throws Exception
- {
- ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader();
- ObjectName mbean = null;
- try
- {
- // Deserialize the transaction if it is there
- MarshalledInvocation mi = (MarshalledInvocation) invocation;
- invocation.setTransaction(importTPC(mi.getTransactionPropagationContext()));
- mbean = (ObjectName) Registry.lookup(invocation.getObjectName());
- // The cl on the thread should be set in another interceptor
- Object obj = serverAction.invoke(mbean,
- "invoke",
- new Object[]{invocation},
- Invocation.INVOKE_SIGNATURE);
- return new MarshalledObject(obj);
- }
- catch (Exception e)
- {
- Throwable th = JMXExceptionDecoder.decode(e);
- if (log.isTraceEnabled())
- log.trace("Failed to invoke on mbean: " + mbean, th);
- if (th instanceof Exception)
- e = (Exception) th;
- throw e;
- }
- finally
- {
- TCLAction.UTIL.setContextClassLoader(oldCl);
- Thread.interrupted(); // clear interruption because this thread may be pooled.
- }
- }
- protected Invoker createDelegateInvoker()
- {
- return new JRMPInvokerProxy(this);
- }
- protected void exportCI() throws Exception
- {
- this.invokerStub = (RemoteStub) UnicastRemoteObject.exportObject
- (this, rmiPort, clientSocketFactory, serverSocketFactory);
- }
- protected void unexportCI() throws Exception
- {
- UnicastRemoteObject.unexportObject(this, true);
- }
- protected void rebind(Context ctx, String name, Object val)
- throws NamingException
- {
- // Bind val to name in ctx, and make sure that all
- // intermediate contexts exist
- Name n = ctx.getNameParser("").parse(name);
- while (n.size() > 1)
- {
- String ctxName = n.get(0);
- try
- {
- ctx = (Context) ctx.lookup(ctxName);
- }
- catch (NameNotFoundException e)
- {
- ctx = ctx.createSubcontext(ctxName);
- }
- n = n.getSuffix(1);
- }
- ctx.rebind(n.get(0), val);
- }
- /**
- * Load and instantiate the clientSocketFactory, serverSocketFactory using
- * the TCL and set the bind address and SSL domain if the serverSocketFactory
- * supports it.
- */
- protected void loadCustomSocketFactories()
- {
- ClassLoader loader = TCLAction.UTIL.getContextClassLoader();
- if( clientSocketFactory == null )
- {
- try
- {
- if (clientSocketFactoryName != null)
- {
- Class csfClass = loader.loadClass(clientSocketFactoryName);
- clientSocketFactory = (RMIClientSocketFactory) csfClass.newInstance();
- }
- }
- catch (Exception e)
- {
- log.error("Failed to load client socket factory", e);
- clientSocketFactory = null;
- }
- }
- if( serverSocketFactory == null )
- {
- try
- {
- if (serverSocketFactoryName != null)
- {
- Class ssfClass = loader.loadClass(serverSocketFactoryName);
- serverSocketFactory = (RMIServerSocketFactory) ssfClass.newInstance();
- if (serverAddress != null)
- {
- // See if the server socket supports setBindAddress(String)
- try
- {
- Class[] parameterTypes = {String.class};
- Method m = ssfClass.getMethod("setBindAddress", parameterTypes);
- Object[] args = {serverAddress};
- m.invoke(serverSocketFactory, args);
- }
- catch (NoSuchMethodException e)
- {
- log.warn("Socket factory does not support setBindAddress(String)");
- // Go with default address
- }
- catch (Exception e)
- {
- log.warn("Failed to setBindAddress=" + serverAddress + " on socket factory", e);
- // Go with default address
- }
- }
- /* See if the server socket supports setSecurityDomain(SecurityDomain)
- if an sslDomain was specified
- */
- if (sslDomain != null)
- {
- try
- {
- InitialContext ctx = new InitialContext();
- SecurityDomain domain = (SecurityDomain) ctx.lookup(sslDomain);
- Class[] parameterTypes = {SecurityDomain.class};
- Method m = ssfClass.getMethod("setSecurityDomain", parameterTypes);
- Object[] args = {domain};
- m.invoke(serverSocketFactory, args);
- }
- catch (NoSuchMethodException e)
- {
- log.error("Socket factory does not support setSecurityDomain(SecurityDomain)");
- }
- catch (Exception e)
- {
- log.error("Failed to setSecurityDomain=" + sslDomain + " on socket factory", e);
- }
- }
- }
- // If a bind address was specified create a DefaultSocketFactory
- else if (serverAddress != null)
- {
- DefaultSocketFactory defaultFactory = new DefaultSocketFactory(backlog);
- serverSocketFactory = defaultFactory;
- try
- {
- defaultFactory.setBindAddress(serverAddress);
- }
- catch (UnknownHostException e)
- {
- log.error("Failed to setBindAddress=" + serverAddress + " on socket factory", e);
- }
- }
- }
- catch (Exception e)
- {
- log.error("operation failed", e);
- serverSocketFactory = null;
- }
- }
- }
- /**
- * Import a transaction propagation context into the local VM, and
- * return the corresponding <code>Transaction</code>.
- *
- * @return A transaction or null if no tpc.
- */
- protected Transaction importTPC(Object tpc)
- {
- if (tpc != null)
- return TransactionPropagationContextUtil.importTPC(tpc);
- return null;
- }
- //
- // Delegate the ServiceMBean details to our support delegate
- //
- public String getName()
- {
- return support.getName();
- }
- public MBeanServer getServer()
- {
- return support.getServer();
- }
- public int getState()
- {
- return support.getState();
- }
- public String getStateString()
- {
- return support.getStateString();
- }
- public void create() throws Exception
- {
- support.create();
- }
- public void start() throws Exception
- {
- support.start();
- }
- public void stop()
- {
- support.stop();
- }
- public void destroy()
- {
- support.destroy();
- }
- public void jbossInternalLifecycle(String method) throws Exception
- {
- support.jbossInternalLifecycle(method);
- }
- public ObjectName preRegister(MBeanServer server, ObjectName name)
- throws Exception
- {
- return support.preRegister(server, name);
- }
- public void postRegister(Boolean registrationDone)
- {
- support.postRegister(registrationDone);
- }
- public void preDeregister() throws Exception
- {
- support.preDeregister();
- }
- public void postDeregister()
- {
- support.postDeregister();
- }
- public void setKernelControllerContext(KernelControllerContext context) throws Exception
- {
- support.setKernelControllerContext(context);
- }
- public void unsetKernelControllerContext(KernelControllerContext context) throws Exception
- {
- support.unsetKernelControllerContext(context);
- }
-
- @Create
- public void pojoCreate() throws Exception
- {
- support.pojoCreate();
- }
-
- @Start
- public void pojoStart() throws Exception
- {
- support.pojoStart();
- }
- @Stop
- public void pojoStop() throws Exception
- {
- support.pojoStop();
- }
-
- @Destroy
- public void pojoDestroy() throws Exception
- {
- support.pojoDestroy();
- }
- interface TCLAction
- {
- class UTIL
- {
- static TCLAction getTCLAction()
- {
- return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
- }
- static ClassLoader getContextClassLoader()
- {
- return getTCLAction().getContextClassLoader();
- }
- static ClassLoader getContextClassLoader(Thread thread)
- {
- return getTCLAction().getContextClassLoader(thread);
- }
- static void setContextClassLoader(ClassLoader cl)
- {
- getTCLAction().setContextClassLoader(cl);
- }
- static void setContextClassLoader(Thread thread, ClassLoader cl)
- {
- getTCLAction().setContextClassLoader(thread, cl);
- }
- }
- TCLAction NON_PRIVILEGED = new TCLAction()
- {
- public ClassLoader getContextClassLoader()
- {
- return Thread.currentThread().getContextClassLoader();
- }
- public ClassLoader getContextClassLoader(Thread thread)
- {
- return thread.getContextClassLoader();
- }
- public void setContextClassLoader(ClassLoader cl)
- {
- Thread.currentThread().setContextClassLoader(cl);
- }
- public void setContextClassLoader(Thread thread, ClassLoader cl)
- {
- thread.setContextClassLoader(cl);
- }
- };
- TCLAction PRIVILEGED = new TCLAction()
- {
- private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction()
- {
- public Object run()
- {
- return Thread.currentThread().getContextClassLoader();
- }
- };
- public ClassLoader getContextClassLoader()
- {
- return (ClassLoader) AccessController.doPrivileged(getTCLPrivilegedAction);
- }
- public ClassLoader getContextClassLoader(final Thread thread)
- {
- return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- return thread.getContextClassLoader();
- }
- });
- }
- public void setContextClassLoader(final ClassLoader cl)
- {
- AccessController.doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- Thread.currentThread().setContextClassLoader(cl);
- return null;
- }
- });
- }
- public void setContextClassLoader(final Thread thread, final ClassLoader cl)
- {
- AccessController.doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- thread.setContextClassLoader(cl);
- return null;
- }
- });
- }
- };
- ClassLoader getContextClassLoader();
- ClassLoader getContextClassLoader(Thread thread);
- void setContextClassLoader(ClassLoader cl);
- void setContextClassLoader(Thread thread, ClassLoader cl);
- }
- /**
- * Perform the MBeanServer.invoke op in a PrivilegedExceptionAction if
- * running with a security manager.
- */
- class MBeanServerAction implements PrivilegedExceptionAction
- {
- private ObjectName target;
- String method;
- Object[] args;
- String[] sig;
- MBeanServerAction()
- {
- }
- MBeanServerAction(ObjectName target, String method, Object[] args, String[] sig)
- {
- this.target = target;
- this.method = method;
- this.args = args;
- this.sig = sig;
- }
- public Object run() throws Exception
- {
- Object rtnValue = support.getServer().invoke(target, method, args, sig);
- return rtnValue;
- }
- Object invoke(ObjectName target, String method, Object[] args, String[] sig)
- throws Exception
- {
- SecurityManager sm = System.getSecurityManager();
- Object rtnValue = null;
- if (sm == null)
- {
- // Direct invocation on MBeanServer
- rtnValue = support.getServer().invoke(target, method, args, sig);
- }
- else
- {
- try
- {
- // Encapsulate the invocation in a PrivilegedExceptionAction
- MBeanServerAction action = new MBeanServerAction(target, method, args, sig);
- rtnValue = AccessController.doPrivileged(action);
- }
- catch (PrivilegedActionException e)
- {
- Exception ex = e.getException();
- throw ex;
- }
- }
- return rtnValue;
- }
- }
- }