--- old/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java 2017-02-01 16:12:52.000000000 +0000 +++ /dev/null 2017-02-01 16:12:52.000000000 +0000 @@ -1,1834 +0,0 @@ -/* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code 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 General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package javax.management.remote.rmi; - -import java.io.IOException; -import java.rmi.MarshalledObject; -import java.rmi.UnmarshalException; -import java.rmi.server.Unreferenced; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permission; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import javax.management.*; -import javax.management.remote.JMXServerErrorException; -import javax.management.remote.NotificationResult; -import javax.security.auth.Subject; -import sun.reflect.misc.ReflectUtil; - -import static com.sun.jmx.mbeanserver.Util.cast; -import com.sun.jmx.remote.internal.ServerCommunicatorAdmin; -import com.sun.jmx.remote.internal.ServerNotifForwarder; -import com.sun.jmx.remote.security.JMXSubjectDomainCombiner; -import com.sun.jmx.remote.security.SubjectDelegator; -import com.sun.jmx.remote.util.ClassLoaderWithRepository; -import com.sun.jmx.remote.util.ClassLogger; -import com.sun.jmx.remote.util.EnvHelp; -import com.sun.jmx.remote.util.OrderClassLoaders; -import javax.management.loading.ClassLoaderRepository; - -/** - *

Implementation of the {@link RMIConnection} interface. User - * code will not usually reference this class.

- * - * @since 1.5 - */ -/* - * Notice that we omit the type parameter from MarshalledObject everywhere, - * even though it would add useful information to the documentation. The - * reason is that it was only added in Mustang (Java SE 6), whereas versions - * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our - * commitments for JSR 255. - */ -public class RMIConnectionImpl implements RMIConnection, Unreferenced { - - /** - * Constructs a new {@link RMIConnection}. This connection can be - * used with the JRMP transport. This object does - * not export itself: it is the responsibility of the caller to - * export it appropriately (see {@link - * RMIJRMPServerImpl#makeClient(String,Subject)}). - * - * @param rmiServer The RMIServerImpl object for which this - * connection is created. The behavior is unspecified if this - * parameter is null. - * @param connectionId The ID for this connection. The behavior - * is unspecified if this parameter is null. - * @param defaultClassLoader The default ClassLoader to be used - * when deserializing marshalled objects. Can be null, to signify - * the bootstrap class loader. - * @param subject the authenticated subject to be used for - * authorization. Can be null, to signify that no subject has - * been authenticated. - * @param env the environment containing attributes for the new - * RMIServerImpl. Can be null, equivalent to an - * empty map. - */ - public RMIConnectionImpl(RMIServerImpl rmiServer, - String connectionId, - ClassLoader defaultClassLoader, - Subject subject, - Map env) { - if (rmiServer == null || connectionId == null) - throw new NullPointerException("Illegal null argument"); - if (env == null) - env = Collections.emptyMap(); - this.rmiServer = rmiServer; - this.connectionId = connectionId; - this.defaultClassLoader = defaultClassLoader; - - this.subjectDelegator = new SubjectDelegator(); - this.subject = subject; - if (subject == null) { - this.acc = null; - this.removeCallerContext = false; - } else { - this.removeCallerContext = - SubjectDelegator.checkRemoveCallerContext(subject); - if (this.removeCallerContext) { - this.acc = - JMXSubjectDomainCombiner.getDomainCombinerContext(subject); - } else { - this.acc = - JMXSubjectDomainCombiner.getContext(subject); - } - } - this.mbeanServer = rmiServer.getMBeanServer(); - - final ClassLoader dcl = defaultClassLoader; - - ClassLoaderRepository repository = AccessController.doPrivileged( - new PrivilegedAction() { - public ClassLoaderRepository run() { - return mbeanServer.getClassLoaderRepository(); - } - }, - withPermissions(new MBeanPermission("*", "getClassLoaderRepository")) - ); - this.classLoaderWithRepository = AccessController.doPrivileged( - new PrivilegedAction() { - public ClassLoaderWithRepository run() { - return new ClassLoaderWithRepository( - repository, - dcl); - } - }, - withPermissions(new RuntimePermission("createClassLoader")) - ); - - this.defaultContextClassLoader = - AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public ClassLoader run() { - return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(), - dcl); - } - }); - - serverCommunicatorAdmin = new - RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env)); - - this.env = env; - } - - private static AccessControlContext withPermissions(Permission ... perms){ - Permissions col = new Permissions(); - - for (Permission thePerm : perms ) { - col.add(thePerm); - } - - final ProtectionDomain pd = new ProtectionDomain(null, col); - return new AccessControlContext( new ProtectionDomain[] { pd }); - } - - private synchronized ServerNotifForwarder getServerNotifFwd() { - // Lazily created when first use. Mainly when - // addNotificationListener is first called. - if (serverNotifForwarder == null) - serverNotifForwarder = - new ServerNotifForwarder(mbeanServer, - env, - rmiServer.getNotifBuffer(), - connectionId); - return serverNotifForwarder; - } - - public String getConnectionId() throws IOException { - // We should call reqIncomming() here... shouldn't we? - return connectionId; - } - - public void close() throws IOException { - final boolean debug = logger.debugOn(); - final String idstr = (debug?"["+this.toString()+"]":null); - - synchronized (this) { - if (terminated) { - if (debug) logger.debug("close",idstr + " already terminated."); - return; - } - - if (debug) logger.debug("close",idstr + " closing."); - - terminated = true; - - if (serverCommunicatorAdmin != null) { - serverCommunicatorAdmin.terminate(); - } - - if (serverNotifForwarder != null) { - serverNotifForwarder.terminate(); - } - } - - rmiServer.clientClosed(this); - - if (debug) logger.debug("close",idstr + " closed."); - } - - public void unreferenced() { - logger.debug("unreferenced", "called"); - try { - close(); - logger.debug("unreferenced", "done"); - } catch (IOException e) { - logger.fine("unreferenced", e); - } - } - - //------------------------------------------------------------------------- - // MBeanServerConnection Wrapper - //------------------------------------------------------------------------- - - public ObjectInstance createMBean(String className, - ObjectName name, - Subject delegationSubject) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - IOException { - try { - final Object params[] = - new Object[] { className, name }; - - if (logger.debugOn()) - logger.debug("createMBean(String,ObjectName)", - "connectionId=" + connectionId +", className=" + - className+", name=" + name); - - return (ObjectInstance) - doPrivilegedOperation( - CREATE_MBEAN, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof InstanceAlreadyExistsException) - throw (InstanceAlreadyExistsException) e; - if (e instanceof MBeanRegistrationException) - throw (MBeanRegistrationException) e; - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof NotCompliantMBeanException) - throw (NotCompliantMBeanException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName, - Subject delegationSubject) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException, - IOException { - try { - final Object params[] = - new Object[] { className, name, loaderName }; - - if (logger.debugOn()) - logger.debug("createMBean(String,ObjectName,ObjectName)", - "connectionId=" + connectionId - +", className=" + className - +", name=" + name - +", loaderName=" + loaderName); - - return (ObjectInstance) - doPrivilegedOperation( - CREATE_MBEAN_LOADER, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof InstanceAlreadyExistsException) - throw (InstanceAlreadyExistsException) e; - if (e instanceof MBeanRegistrationException) - throw (MBeanRegistrationException) e; - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof NotCompliantMBeanException) - throw (NotCompliantMBeanException) e; - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public ObjectInstance createMBean(String className, - ObjectName name, - MarshalledObject params, - String signature[], - Subject delegationSubject) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - IOException { - - final Object[] values; - final boolean debug = logger.debugOn(); - - if (debug) logger.debug( - "createMBean(String,ObjectName,Object[],String[])", - "connectionId=" + connectionId - +", unwrapping parameters using classLoaderWithRepository."); - - values = - nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject)); - - try { - final Object params2[] = - new Object[] { className, name, values, - nullIsEmpty(signature) }; - - if (debug) - logger.debug("createMBean(String,ObjectName,Object[],String[])", - "connectionId=" + connectionId - +", className=" + className - +", name=" + name - +", signature=" + strings(signature)); - - return (ObjectInstance) - doPrivilegedOperation( - CREATE_MBEAN_PARAMS, - params2, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof InstanceAlreadyExistsException) - throw (InstanceAlreadyExistsException) e; - if (e instanceof MBeanRegistrationException) - throw (MBeanRegistrationException) e; - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof NotCompliantMBeanException) - throw (NotCompliantMBeanException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName, - MarshalledObject params, - String signature[], - Subject delegationSubject) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException, - IOException { - - final Object[] values; - final boolean debug = logger.debugOn(); - - if (debug) logger.debug( - "createMBean(String,ObjectName,ObjectName,Object[],String[])", - "connectionId=" + connectionId - +", unwrapping params with MBean extended ClassLoader."); - - values = nullIsEmpty(unwrap(params, - getClassLoader(loaderName), - defaultClassLoader, - Object[].class,delegationSubject)); - - try { - final Object params2[] = - new Object[] { className, name, loaderName, values, - nullIsEmpty(signature) }; - - if (debug) logger.debug( - "createMBean(String,ObjectName,ObjectName,Object[],String[])", - "connectionId=" + connectionId - +", className=" + className - +", name=" + name - +", loaderName=" + loaderName - +", signature=" + strings(signature)); - - return (ObjectInstance) - doPrivilegedOperation( - CREATE_MBEAN_LOADER_PARAMS, - params2, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof InstanceAlreadyExistsException) - throw (InstanceAlreadyExistsException) e; - if (e instanceof MBeanRegistrationException) - throw (MBeanRegistrationException) e; - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof NotCompliantMBeanException) - throw (NotCompliantMBeanException) e; - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public void unregisterMBean(ObjectName name, Subject delegationSubject) - throws - InstanceNotFoundException, - MBeanRegistrationException, - IOException { - try { - final Object params[] = new Object[] { name }; - - if (logger.debugOn()) logger.debug("unregisterMBean", - "connectionId=" + connectionId - +", name="+name); - - doPrivilegedOperation( - UNREGISTER_MBEAN, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof MBeanRegistrationException) - throw (MBeanRegistrationException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public ObjectInstance getObjectInstance(ObjectName name, - Subject delegationSubject) - throws - InstanceNotFoundException, - IOException { - - checkNonNull("ObjectName", name); - - try { - final Object params[] = new Object[] { name }; - - if (logger.debugOn()) logger.debug("getObjectInstance", - "connectionId=" + connectionId - +", name="+name); - - return (ObjectInstance) - doPrivilegedOperation( - GET_OBJECT_INSTANCE, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public Set - queryMBeans(ObjectName name, - MarshalledObject query, - Subject delegationSubject) - throws IOException { - final QueryExp queryValue; - final boolean debug=logger.debugOn(); - - if (debug) logger.debug("queryMBeans", - "connectionId=" + connectionId - +" unwrapping query with defaultClassLoader."); - - queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject); - - try { - final Object params[] = new Object[] { name, queryValue }; - - if (debug) logger.debug("queryMBeans", - "connectionId=" + connectionId - +", name="+name +", query="+query); - - return cast( - doPrivilegedOperation( - QUERY_MBEANS, - params, - delegationSubject)); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public Set - queryNames(ObjectName name, - MarshalledObject query, - Subject delegationSubject) - throws IOException { - final QueryExp queryValue; - final boolean debug=logger.debugOn(); - - if (debug) logger.debug("queryNames", - "connectionId=" + connectionId - +" unwrapping query with defaultClassLoader."); - - queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject); - - try { - final Object params[] = new Object[] { name, queryValue }; - - if (debug) logger.debug("queryNames", - "connectionId=" + connectionId - +", name="+name +", query="+query); - - return cast( - doPrivilegedOperation( - QUERY_NAMES, - params, - delegationSubject)); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public boolean isRegistered(ObjectName name, - Subject delegationSubject) throws IOException { - try { - final Object params[] = new Object[] { name }; - return ((Boolean) - doPrivilegedOperation( - IS_REGISTERED, - params, - delegationSubject)).booleanValue(); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public Integer getMBeanCount(Subject delegationSubject) - throws IOException { - try { - final Object params[] = new Object[] { }; - - if (logger.debugOn()) logger.debug("getMBeanCount", - "connectionId=" + connectionId); - - return (Integer) - doPrivilegedOperation( - GET_MBEAN_COUNT, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public Object getAttribute(ObjectName name, - String attribute, - Subject delegationSubject) - throws - MBeanException, - AttributeNotFoundException, - InstanceNotFoundException, - ReflectionException, - IOException { - try { - final Object params[] = new Object[] { name, attribute }; - if (logger.debugOn()) logger.debug("getAttribute", - "connectionId=" + connectionId - +", name=" + name - +", attribute="+ attribute); - - return - doPrivilegedOperation( - GET_ATTRIBUTE, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof AttributeNotFoundException) - throw (AttributeNotFoundException) e; - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public AttributeList getAttributes(ObjectName name, - String[] attributes, - Subject delegationSubject) - throws - InstanceNotFoundException, - ReflectionException, - IOException { - try { - final Object params[] = new Object[] { name, attributes }; - - if (logger.debugOn()) logger.debug("getAttributes", - "connectionId=" + connectionId - +", name=" + name - +", attributes="+ strings(attributes)); - - return (AttributeList) - doPrivilegedOperation( - GET_ATTRIBUTES, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public void setAttribute(ObjectName name, - MarshalledObject attribute, - Subject delegationSubject) - throws - InstanceNotFoundException, - AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException, - IOException { - final Attribute attr; - final boolean debug=logger.debugOn(); - - if (debug) logger.debug("setAttribute", - "connectionId=" + connectionId - +" unwrapping attribute with MBean extended ClassLoader."); - - attr = unwrap(attribute, - getClassLoaderFor(name), - defaultClassLoader, - Attribute.class, delegationSubject); - - try { - final Object params[] = new Object[] { name, attr }; - - if (debug) logger.debug("setAttribute", - "connectionId=" + connectionId - +", name="+name - +", attribute name="+attr.getName()); - - doPrivilegedOperation( - SET_ATTRIBUTE, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof AttributeNotFoundException) - throw (AttributeNotFoundException) e; - if (e instanceof InvalidAttributeValueException) - throw (InvalidAttributeValueException) e; - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public AttributeList setAttributes(ObjectName name, - MarshalledObject attributes, - Subject delegationSubject) - throws - InstanceNotFoundException, - ReflectionException, - IOException { - final AttributeList attrlist; - final boolean debug=logger.debugOn(); - - if (debug) logger.debug("setAttributes", - "connectionId=" + connectionId - +" unwrapping attributes with MBean extended ClassLoader."); - - attrlist = - unwrap(attributes, - getClassLoaderFor(name), - defaultClassLoader, - AttributeList.class, delegationSubject); - - try { - final Object params[] = new Object[] { name, attrlist }; - - if (debug) logger.debug("setAttributes", - "connectionId=" + connectionId - +", name="+name - +", attribute names="+RMIConnector.getAttributesNames(attrlist)); - - return (AttributeList) - doPrivilegedOperation( - SET_ATTRIBUTES, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public Object invoke(ObjectName name, - String operationName, - MarshalledObject params, - String signature[], - Subject delegationSubject) - throws - InstanceNotFoundException, - MBeanException, - ReflectionException, - IOException { - - checkNonNull("ObjectName", name); - checkNonNull("Operation name", operationName); - - final Object[] values; - final boolean debug=logger.debugOn(); - - if (debug) logger.debug("invoke", - "connectionId=" + connectionId - +" unwrapping params with MBean extended ClassLoader."); - - values = nullIsEmpty(unwrap(params, - getClassLoaderFor(name), - defaultClassLoader, - Object[].class, delegationSubject)); - - try { - final Object params2[] = - new Object[] { name, operationName, values, - nullIsEmpty(signature) }; - - if (debug) logger.debug("invoke", - "connectionId=" + connectionId - +", name="+name - +", operationName="+operationName - +", signature="+strings(signature)); - - return - doPrivilegedOperation( - INVOKE, - params2, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof MBeanException) - throw (MBeanException) e; - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public String getDefaultDomain(Subject delegationSubject) - throws IOException { - try { - final Object params[] = new Object[] { }; - - if (logger.debugOn()) logger.debug("getDefaultDomain", - "connectionId=" + connectionId); - - return (String) - doPrivilegedOperation( - GET_DEFAULT_DOMAIN, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public String[] getDomains(Subject delegationSubject) throws IOException { - try { - final Object params[] = new Object[] { }; - - if (logger.debugOn()) logger.debug("getDomains", - "connectionId=" + connectionId); - - return (String[]) - doPrivilegedOperation( - GET_DOMAINS, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject) - throws - InstanceNotFoundException, - IntrospectionException, - ReflectionException, - IOException { - - checkNonNull("ObjectName", name); - - try { - final Object params[] = new Object[] { name }; - - if (logger.debugOn()) logger.debug("getMBeanInfo", - "connectionId=" + connectionId - +", name="+name); - - return (MBeanInfo) - doPrivilegedOperation( - GET_MBEAN_INFO, - params, - delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof IntrospectionException) - throw (IntrospectionException) e; - if (e instanceof ReflectionException) - throw (ReflectionException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - public boolean isInstanceOf(ObjectName name, - String className, - Subject delegationSubject) - throws InstanceNotFoundException, IOException { - - checkNonNull("ObjectName", name); - - try { - final Object params[] = new Object[] { name, className }; - - if (logger.debugOn()) logger.debug("isInstanceOf", - "connectionId=" + connectionId - +", name="+name - +", className="+className); - - return ((Boolean) - doPrivilegedOperation( - IS_INSTANCE_OF, - params, - delegationSubject)).booleanValue(); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof InstanceNotFoundException) - throw (InstanceNotFoundException) e; - if (e instanceof IOException) - throw (IOException) e; - throw newIOException("Got unexpected server exception: " + e, e); - } - } - - @SuppressWarnings("rawtypes") // MarshalledObject - public Integer[] addNotificationListeners(ObjectName[] names, - MarshalledObject[] filters, - Subject[] delegationSubjects) - throws InstanceNotFoundException, IOException { - - if (names == null || filters == null) { - throw new IllegalArgumentException("Got null arguments."); - } - - Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects : - new Subject[names.length]; - if (names.length != filters.length || filters.length != sbjs.length) { - final String msg = - "The value lengths of 3 parameters are not same."; - throw new IllegalArgumentException(msg); - } - - for (int i=0; i action = - new PrivilegedAction() { - public NotificationResult run() { - return getServerNotifFwd().fetchNotifs(csn, t, mn); - } - }; - if (acc == null) - return action.run(); - else - return AccessController.doPrivileged(action, acc); - } finally { - serverCommunicatorAdmin.rspOutgoing(); - } - } - - /** - *

Returns a string representation of this object. In general, - * the toString method returns a string that - * "textually represents" this object. The result should be a - * concise but informative representation that is easy for a - * person to read.

- * - * @return a String representation of this object. - **/ - @Override - public String toString() { - return super.toString() + ": connectionId=" + connectionId; - } - - //------------------------------------------------------------------------ - // private classes - //------------------------------------------------------------------------ - - private class PrivilegedOperation - implements PrivilegedExceptionAction { - - public PrivilegedOperation(int operation, Object[] params) { - this.operation = operation; - this.params = params; - } - - public Object run() throws Exception { - return doOperation(operation, params); - } - - private int operation; - private Object[] params; - } - - //------------------------------------------------------------------------ - // private classes - //------------------------------------------------------------------------ - private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin { - public RMIServerCommunicatorAdmin(long timeout) { - super(timeout); - } - - protected void doStop() { - try { - close(); - } catch (IOException ie) { - logger.warning("RMIServerCommunicatorAdmin-doStop", - "Failed to close: " + ie); - logger.debug("RMIServerCommunicatorAdmin-doStop",ie); - } - } - - } - - - //------------------------------------------------------------------------ - // private methods - //------------------------------------------------------------------------ - - private ClassLoader getClassLoader(final ObjectName name) - throws InstanceNotFoundException { - try { - return - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public ClassLoader run() throws InstanceNotFoundException { - return mbeanServer.getClassLoader(name); - } - }, - withPermissions(new MBeanPermission("*", "getClassLoader")) - ); - } catch (PrivilegedActionException pe) { - throw (InstanceNotFoundException) extractException(pe); - } - } - - private ClassLoader getClassLoaderFor(final ObjectName name) - throws InstanceNotFoundException { - try { - return (ClassLoader) - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Object run() throws InstanceNotFoundException { - return mbeanServer.getClassLoaderFor(name); - } - }, - withPermissions(new MBeanPermission("*", "getClassLoaderFor")) - ); - } catch (PrivilegedActionException pe) { - throw (InstanceNotFoundException) extractException(pe); - } - } - - private Object doPrivilegedOperation(final int operation, - final Object[] params, - final Subject delegationSubject) - throws PrivilegedActionException, IOException { - - serverCommunicatorAdmin.reqIncoming(); - try { - - final AccessControlContext reqACC; - if (delegationSubject == null) - reqACC = acc; - else { - if (subject == null) { - final String msg = - "Subject delegation cannot be enabled unless " + - "an authenticated subject is put in place"; - throw new SecurityException(msg); - } - reqACC = subjectDelegator.delegatedContext( - acc, delegationSubject, removeCallerContext); - } - - PrivilegedOperation op = - new PrivilegedOperation(operation, params); - if (reqACC == null) { - try { - return op.run(); - } catch (Exception e) { - if (e instanceof RuntimeException) - throw (RuntimeException) e; - throw new PrivilegedActionException(e); - } - } else { - return AccessController.doPrivileged(op, reqACC); - } - } catch (Error e) { - throw new JMXServerErrorException(e.toString(),e); - } finally { - serverCommunicatorAdmin.rspOutgoing(); - } - } - - private Object doOperation(int operation, Object[] params) - throws Exception { - - switch (operation) { - - case CREATE_MBEAN: - return mbeanServer.createMBean((String)params[0], - (ObjectName)params[1]); - - case CREATE_MBEAN_LOADER: - return mbeanServer.createMBean((String)params[0], - (ObjectName)params[1], - (ObjectName)params[2]); - - case CREATE_MBEAN_PARAMS: - return mbeanServer.createMBean((String)params[0], - (ObjectName)params[1], - (Object[])params[2], - (String[])params[3]); - - case CREATE_MBEAN_LOADER_PARAMS: - return mbeanServer.createMBean((String)params[0], - (ObjectName)params[1], - (ObjectName)params[2], - (Object[])params[3], - (String[])params[4]); - - case GET_ATTRIBUTE: - return mbeanServer.getAttribute((ObjectName)params[0], - (String)params[1]); - - case GET_ATTRIBUTES: - return mbeanServer.getAttributes((ObjectName)params[0], - (String[])params[1]); - - case GET_DEFAULT_DOMAIN: - return mbeanServer.getDefaultDomain(); - - case GET_DOMAINS: - return mbeanServer.getDomains(); - - case GET_MBEAN_COUNT: - return mbeanServer.getMBeanCount(); - - case GET_MBEAN_INFO: - return mbeanServer.getMBeanInfo((ObjectName)params[0]); - - case GET_OBJECT_INSTANCE: - return mbeanServer.getObjectInstance((ObjectName)params[0]); - - case INVOKE: - return mbeanServer.invoke((ObjectName)params[0], - (String)params[1], - (Object[])params[2], - (String[])params[3]); - - case IS_INSTANCE_OF: - return mbeanServer.isInstanceOf((ObjectName)params[0], - (String)params[1]) - ? Boolean.TRUE : Boolean.FALSE; - - case IS_REGISTERED: - return mbeanServer.isRegistered((ObjectName)params[0]) - ? Boolean.TRUE : Boolean.FALSE; - - case QUERY_MBEANS: - return mbeanServer.queryMBeans((ObjectName)params[0], - (QueryExp)params[1]); - - case QUERY_NAMES: - return mbeanServer.queryNames((ObjectName)params[0], - (QueryExp)params[1]); - - case SET_ATTRIBUTE: - mbeanServer.setAttribute((ObjectName)params[0], - (Attribute)params[1]); - return null; - - case SET_ATTRIBUTES: - return mbeanServer.setAttributes((ObjectName)params[0], - (AttributeList)params[1]); - - case UNREGISTER_MBEAN: - mbeanServer.unregisterMBean((ObjectName)params[0]); - return null; - - case ADD_NOTIFICATION_LISTENERS: - return getServerNotifFwd().addNotificationListener( - (ObjectName)params[0], - (NotificationFilter)params[1]); - - case ADD_NOTIFICATION_LISTENER_OBJECTNAME: - mbeanServer.addNotificationListener((ObjectName)params[0], - (ObjectName)params[1], - (NotificationFilter)params[2], - params[3]); - return null; - - case REMOVE_NOTIFICATION_LISTENER: - getServerNotifFwd().removeNotificationListener( - (ObjectName)params[0], - (Integer[])params[1]); - return null; - - case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME: - mbeanServer.removeNotificationListener((ObjectName)params[0], - (ObjectName)params[1]); - return null; - - case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK: - mbeanServer.removeNotificationListener( - (ObjectName)params[0], - (ObjectName)params[1], - (NotificationFilter)params[2], - params[3]); - return null; - - default: - throw new IllegalArgumentException("Invalid operation"); - } - } - - private static class SetCcl implements PrivilegedExceptionAction { - private final ClassLoader classLoader; - - SetCcl(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public ClassLoader run() { - Thread currentThread = Thread.currentThread(); - ClassLoader old = currentThread.getContextClassLoader(); - currentThread.setContextClassLoader(classLoader); - return old; - } - } - - private T unwrap(final MarshalledObject mo, - final ClassLoader cl, - final Class wrappedClass, - Subject delegationSubject) - throws IOException { - if (mo == null) { - return null; - } - try { - final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl)); - try{ - final AccessControlContext reqACC; - if (delegationSubject == null) - reqACC = acc; - else { - if (subject == null) { - final String msg = - "Subject delegation cannot be enabled unless " + - "an authenticated subject is put in place"; - throw new SecurityException(msg); - } - reqACC = subjectDelegator.delegatedContext( - acc, delegationSubject, removeCallerContext); - } - if(reqACC != null){ - return AccessController.doPrivileged( - (PrivilegedExceptionAction) () -> - wrappedClass.cast(mo.get()), reqACC); - }else{ - return wrappedClass.cast(mo.get()); - } - }finally{ - AccessController.doPrivileged(new SetCcl(old)); - } - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) { - throw (IOException) e; - } - if (e instanceof ClassNotFoundException) { - throw new UnmarshalException(e.toString(), e); - } - logger.warning("unwrap", "Failed to unmarshall object: " + e); - logger.debug("unwrap", e); - }catch (ClassNotFoundException ex) { - logger.warning("unwrap", "Failed to unmarshall object: " + ex); - logger.debug("unwrap", ex); - throw new UnmarshalException(ex.toString(), ex); - } - return null; - } - - private T unwrap(final MarshalledObject mo, - final ClassLoader cl1, - final ClassLoader cl2, - final Class wrappedClass, - Subject delegationSubject) - throws IOException { - if (mo == null) { - return null; - } - try { - ClassLoader orderCL = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public ClassLoader run() throws Exception { - return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(), - new OrderClassLoaders(cl1, cl2)); - } - } - ); - return unwrap(mo, orderCL, wrappedClass,delegationSubject); - } catch (PrivilegedActionException pe) { - Exception e = extractException(pe); - if (e instanceof IOException) { - throw (IOException) e; - } - if (e instanceof ClassNotFoundException) { - throw new UnmarshalException(e.toString(), e); - } - logger.warning("unwrap", "Failed to unmarshall object: " + e); - logger.debug("unwrap", e); - } - return null; - } - - /** - * Construct a new IOException with a nested exception. - * The nested exception is set only if JDK {@literal >= 1.4} - */ - private static IOException newIOException(String message, - Throwable cause) { - final IOException x = new IOException(message); - return EnvHelp.initCause(x,cause); - } - - /** - * Iterate until we extract the real exception - * from a stack of PrivilegedActionExceptions. - */ - private static Exception extractException(Exception e) { - while (e instanceof PrivilegedActionException) { - e = ((PrivilegedActionException)e).getException(); - } - return e; - } - - private static final Object[] NO_OBJECTS = new Object[0]; - private static final String[] NO_STRINGS = new String[0]; - - /* - * The JMX spec doesn't explicitly say that a null Object[] or - * String[] in e.g. MBeanServer.invoke is equivalent to an empty - * array, but the RI behaves that way. In the interests of - * maximal interoperability, we make it so even when we're - * connected to some other JMX implementation that might not do - * that. This should be clarified in the next version of JMX. - */ - private static Object[] nullIsEmpty(Object[] array) { - return (array == null) ? NO_OBJECTS : array; - } - - private static String[] nullIsEmpty(String[] array) { - return (array == null) ? NO_STRINGS : array; - } - - /* - * Similarly, the JMX spec says for some but not all methods in - * MBeanServer that take an ObjectName target, that if it's null - * you get this exception. We specify it for all of them, and - * make it so for the ones where it's not specified in JMX even if - * the JMX implementation doesn't do so. - */ - private static void checkNonNull(String what, Object x) { - if (x == null) { - RuntimeException wrapped = - new IllegalArgumentException(what + " must not be null"); - throw new RuntimeOperationsException(wrapped); - } - } - - //------------------------------------------------------------------------ - // private variables - //------------------------------------------------------------------------ - - private final Subject subject; - - private final SubjectDelegator subjectDelegator; - - private final boolean removeCallerContext; - - private final AccessControlContext acc; - - private final RMIServerImpl rmiServer; - - private final MBeanServer mbeanServer; - - private final ClassLoader defaultClassLoader; - - private final ClassLoader defaultContextClassLoader; - - private final ClassLoaderWithRepository classLoaderWithRepository; - - private boolean terminated = false; - - private final String connectionId; - - private final ServerCommunicatorAdmin serverCommunicatorAdmin; - - // Method IDs for doOperation - //--------------------------- - - private final static int - ADD_NOTIFICATION_LISTENERS = 1; - private final static int - ADD_NOTIFICATION_LISTENER_OBJECTNAME = 2; - private final static int - CREATE_MBEAN = 3; - private final static int - CREATE_MBEAN_PARAMS = 4; - private final static int - CREATE_MBEAN_LOADER = 5; - private final static int - CREATE_MBEAN_LOADER_PARAMS = 6; - private final static int - GET_ATTRIBUTE = 7; - private final static int - GET_ATTRIBUTES = 8; - private final static int - GET_DEFAULT_DOMAIN = 9; - private final static int - GET_DOMAINS = 10; - private final static int - GET_MBEAN_COUNT = 11; - private final static int - GET_MBEAN_INFO = 12; - private final static int - GET_OBJECT_INSTANCE = 13; - private final static int - INVOKE = 14; - private final static int - IS_INSTANCE_OF = 15; - private final static int - IS_REGISTERED = 16; - private final static int - QUERY_MBEANS = 17; - private final static int - QUERY_NAMES = 18; - private final static int - REMOVE_NOTIFICATION_LISTENER = 19; - private final static int - REMOVE_NOTIFICATION_LISTENER_OBJECTNAME = 20; - private final static int - REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 21; - private final static int - SET_ATTRIBUTE = 22; - private final static int - SET_ATTRIBUTES = 23; - private final static int - UNREGISTER_MBEAN = 24; - - // SERVER NOTIFICATION - //-------------------- - - private ServerNotifForwarder serverNotifForwarder; - private Map env; - - // TRACES & DEBUG - //--------------- - - private static String objects(final Object[] objs) { - if (objs == null) - return "null"; - else - return Arrays.asList(objs).toString(); - } - - private static String strings(final String[] strs) { - return objects(strs); - } - - private static final ClassLogger logger = - new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl"); - - private static final class CombinedClassLoader extends ClassLoader { - - private final static class ClassLoaderWrapper extends ClassLoader { - ClassLoaderWrapper(ClassLoader cl) { - super(cl); - } - - @Override - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - return super.loadClass(name, resolve); - } - }; - - final ClassLoaderWrapper defaultCL; - - private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) { - super(parent); - this.defaultCL = new ClassLoaderWrapper(defaultCL); - } - - @Override - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - ReflectUtil.checkPackageAccess(name); - try { - super.loadClass(name, resolve); - } catch(Exception e) { - for(Throwable t = e; t != null; t = t.getCause()) { - if(t instanceof SecurityException) { - throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e); - } - } - } - final Class cl = defaultCL.loadClass(name, resolve); - return cl; - } - - } -} --- /dev/null 2017-02-01 16:12:52.000000000 +0000 +++ new/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java 2017-02-01 16:12:52.000000000 +0000 @@ -0,0 +1,1834 @@ +/* + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.management.remote.rmi; + +import java.io.IOException; +import java.rmi.MarshalledObject; +import java.rmi.UnmarshalException; +import java.rmi.server.Unreferenced; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permission; +import java.security.Permissions; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import javax.management.*; +import javax.management.remote.JMXServerErrorException; +import javax.management.remote.NotificationResult; +import javax.security.auth.Subject; +import sun.reflect.misc.ReflectUtil; + +import static javax.management.remote.rmi.RMIConnector.Util.cast; +import com.sun.jmx.remote.internal.ServerCommunicatorAdmin; +import com.sun.jmx.remote.internal.ServerNotifForwarder; +import com.sun.jmx.remote.security.JMXSubjectDomainCombiner; +import com.sun.jmx.remote.security.SubjectDelegator; +import com.sun.jmx.remote.util.ClassLoaderWithRepository; +import com.sun.jmx.remote.util.ClassLogger; +import com.sun.jmx.remote.util.EnvHelp; +import com.sun.jmx.remote.util.OrderClassLoaders; +import javax.management.loading.ClassLoaderRepository; + +/** + *

Implementation of the {@link RMIConnection} interface. User + * code will not usually reference this class.

+ * + * @since 1.5 + */ +/* + * Notice that we omit the type parameter from MarshalledObject everywhere, + * even though it would add useful information to the documentation. The + * reason is that it was only added in Mustang (Java SE 6), whereas versions + * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our + * commitments for JSR 255. + */ +public class RMIConnectionImpl implements RMIConnection, Unreferenced { + + /** + * Constructs a new {@link RMIConnection}. This connection can be + * used with the JRMP transport. This object does + * not export itself: it is the responsibility of the caller to + * export it appropriately (see {@link + * RMIJRMPServerImpl#makeClient(String,Subject)}). + * + * @param rmiServer The RMIServerImpl object for which this + * connection is created. The behavior is unspecified if this + * parameter is null. + * @param connectionId The ID for this connection. The behavior + * is unspecified if this parameter is null. + * @param defaultClassLoader The default ClassLoader to be used + * when deserializing marshalled objects. Can be null, to signify + * the bootstrap class loader. + * @param subject the authenticated subject to be used for + * authorization. Can be null, to signify that no subject has + * been authenticated. + * @param env the environment containing attributes for the new + * RMIServerImpl. Can be null, equivalent to an + * empty map. + */ + public RMIConnectionImpl(RMIServerImpl rmiServer, + String connectionId, + ClassLoader defaultClassLoader, + Subject subject, + Map env) { + if (rmiServer == null || connectionId == null) + throw new NullPointerException("Illegal null argument"); + if (env == null) + env = Collections.emptyMap(); + this.rmiServer = rmiServer; + this.connectionId = connectionId; + this.defaultClassLoader = defaultClassLoader; + + this.subjectDelegator = new SubjectDelegator(); + this.subject = subject; + if (subject == null) { + this.acc = null; + this.removeCallerContext = false; + } else { + this.removeCallerContext = + SubjectDelegator.checkRemoveCallerContext(subject); + if (this.removeCallerContext) { + this.acc = + JMXSubjectDomainCombiner.getDomainCombinerContext(subject); + } else { + this.acc = + JMXSubjectDomainCombiner.getContext(subject); + } + } + this.mbeanServer = rmiServer.getMBeanServer(); + + final ClassLoader dcl = defaultClassLoader; + + ClassLoaderRepository repository = AccessController.doPrivileged( + new PrivilegedAction() { + public ClassLoaderRepository run() { + return mbeanServer.getClassLoaderRepository(); + } + }, + withPermissions(new MBeanPermission("*", "getClassLoaderRepository")) + ); + this.classLoaderWithRepository = AccessController.doPrivileged( + new PrivilegedAction() { + public ClassLoaderWithRepository run() { + return new ClassLoaderWithRepository( + repository, + dcl); + } + }, + withPermissions(new RuntimePermission("createClassLoader")) + ); + + this.defaultContextClassLoader = + AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public ClassLoader run() { + return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(), + dcl); + } + }); + + serverCommunicatorAdmin = new + RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env)); + + this.env = env; + } + + private static AccessControlContext withPermissions(Permission ... perms){ + Permissions col = new Permissions(); + + for (Permission thePerm : perms ) { + col.add(thePerm); + } + + final ProtectionDomain pd = new ProtectionDomain(null, col); + return new AccessControlContext( new ProtectionDomain[] { pd }); + } + + private synchronized ServerNotifForwarder getServerNotifFwd() { + // Lazily created when first use. Mainly when + // addNotificationListener is first called. + if (serverNotifForwarder == null) + serverNotifForwarder = + new ServerNotifForwarder(mbeanServer, + env, + rmiServer.getNotifBuffer(), + connectionId); + return serverNotifForwarder; + } + + public String getConnectionId() throws IOException { + // We should call reqIncomming() here... shouldn't we? + return connectionId; + } + + public void close() throws IOException { + final boolean debug = logger.debugOn(); + final String idstr = (debug?"["+this.toString()+"]":null); + + synchronized (this) { + if (terminated) { + if (debug) logger.debug("close",idstr + " already terminated."); + return; + } + + if (debug) logger.debug("close",idstr + " closing."); + + terminated = true; + + if (serverCommunicatorAdmin != null) { + serverCommunicatorAdmin.terminate(); + } + + if (serverNotifForwarder != null) { + serverNotifForwarder.terminate(); + } + } + + rmiServer.clientClosed(this); + + if (debug) logger.debug("close",idstr + " closed."); + } + + public void unreferenced() { + logger.debug("unreferenced", "called"); + try { + close(); + logger.debug("unreferenced", "done"); + } catch (IOException e) { + logger.fine("unreferenced", e); + } + } + + //------------------------------------------------------------------------- + // MBeanServerConnection Wrapper + //------------------------------------------------------------------------- + + public ObjectInstance createMBean(String className, + ObjectName name, + Subject delegationSubject) + throws + ReflectionException, + InstanceAlreadyExistsException, + MBeanRegistrationException, + MBeanException, + NotCompliantMBeanException, + IOException { + try { + final Object params[] = + new Object[] { className, name }; + + if (logger.debugOn()) + logger.debug("createMBean(String,ObjectName)", + "connectionId=" + connectionId +", className=" + + className+", name=" + name); + + return (ObjectInstance) + doPrivilegedOperation( + CREATE_MBEAN, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof InstanceAlreadyExistsException) + throw (InstanceAlreadyExistsException) e; + if (e instanceof MBeanRegistrationException) + throw (MBeanRegistrationException) e; + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof NotCompliantMBeanException) + throw (NotCompliantMBeanException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public ObjectInstance createMBean(String className, + ObjectName name, + ObjectName loaderName, + Subject delegationSubject) + throws + ReflectionException, + InstanceAlreadyExistsException, + MBeanRegistrationException, + MBeanException, + NotCompliantMBeanException, + InstanceNotFoundException, + IOException { + try { + final Object params[] = + new Object[] { className, name, loaderName }; + + if (logger.debugOn()) + logger.debug("createMBean(String,ObjectName,ObjectName)", + "connectionId=" + connectionId + +", className=" + className + +", name=" + name + +", loaderName=" + loaderName); + + return (ObjectInstance) + doPrivilegedOperation( + CREATE_MBEAN_LOADER, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof InstanceAlreadyExistsException) + throw (InstanceAlreadyExistsException) e; + if (e instanceof MBeanRegistrationException) + throw (MBeanRegistrationException) e; + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof NotCompliantMBeanException) + throw (NotCompliantMBeanException) e; + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public ObjectInstance createMBean(String className, + ObjectName name, + MarshalledObject params, + String signature[], + Subject delegationSubject) + throws + ReflectionException, + InstanceAlreadyExistsException, + MBeanRegistrationException, + MBeanException, + NotCompliantMBeanException, + IOException { + + final Object[] values; + final boolean debug = logger.debugOn(); + + if (debug) logger.debug( + "createMBean(String,ObjectName,Object[],String[])", + "connectionId=" + connectionId + +", unwrapping parameters using classLoaderWithRepository."); + + values = + nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject)); + + try { + final Object params2[] = + new Object[] { className, name, values, + nullIsEmpty(signature) }; + + if (debug) + logger.debug("createMBean(String,ObjectName,Object[],String[])", + "connectionId=" + connectionId + +", className=" + className + +", name=" + name + +", signature=" + strings(signature)); + + return (ObjectInstance) + doPrivilegedOperation( + CREATE_MBEAN_PARAMS, + params2, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof InstanceAlreadyExistsException) + throw (InstanceAlreadyExistsException) e; + if (e instanceof MBeanRegistrationException) + throw (MBeanRegistrationException) e; + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof NotCompliantMBeanException) + throw (NotCompliantMBeanException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public ObjectInstance createMBean(String className, + ObjectName name, + ObjectName loaderName, + MarshalledObject params, + String signature[], + Subject delegationSubject) + throws + ReflectionException, + InstanceAlreadyExistsException, + MBeanRegistrationException, + MBeanException, + NotCompliantMBeanException, + InstanceNotFoundException, + IOException { + + final Object[] values; + final boolean debug = logger.debugOn(); + + if (debug) logger.debug( + "createMBean(String,ObjectName,ObjectName,Object[],String[])", + "connectionId=" + connectionId + +", unwrapping params with MBean extended ClassLoader."); + + values = nullIsEmpty(unwrap(params, + getClassLoader(loaderName), + defaultClassLoader, + Object[].class,delegationSubject)); + + try { + final Object params2[] = + new Object[] { className, name, loaderName, values, + nullIsEmpty(signature) }; + + if (debug) logger.debug( + "createMBean(String,ObjectName,ObjectName,Object[],String[])", + "connectionId=" + connectionId + +", className=" + className + +", name=" + name + +", loaderName=" + loaderName + +", signature=" + strings(signature)); + + return (ObjectInstance) + doPrivilegedOperation( + CREATE_MBEAN_LOADER_PARAMS, + params2, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof InstanceAlreadyExistsException) + throw (InstanceAlreadyExistsException) e; + if (e instanceof MBeanRegistrationException) + throw (MBeanRegistrationException) e; + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof NotCompliantMBeanException) + throw (NotCompliantMBeanException) e; + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public void unregisterMBean(ObjectName name, Subject delegationSubject) + throws + InstanceNotFoundException, + MBeanRegistrationException, + IOException { + try { + final Object params[] = new Object[] { name }; + + if (logger.debugOn()) logger.debug("unregisterMBean", + "connectionId=" + connectionId + +", name="+name); + + doPrivilegedOperation( + UNREGISTER_MBEAN, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof MBeanRegistrationException) + throw (MBeanRegistrationException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public ObjectInstance getObjectInstance(ObjectName name, + Subject delegationSubject) + throws + InstanceNotFoundException, + IOException { + + checkNonNull("ObjectName", name); + + try { + final Object params[] = new Object[] { name }; + + if (logger.debugOn()) logger.debug("getObjectInstance", + "connectionId=" + connectionId + +", name="+name); + + return (ObjectInstance) + doPrivilegedOperation( + GET_OBJECT_INSTANCE, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public Set + queryMBeans(ObjectName name, + MarshalledObject query, + Subject delegationSubject) + throws IOException { + final QueryExp queryValue; + final boolean debug=logger.debugOn(); + + if (debug) logger.debug("queryMBeans", + "connectionId=" + connectionId + +" unwrapping query with defaultClassLoader."); + + queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject); + + try { + final Object params[] = new Object[] { name, queryValue }; + + if (debug) logger.debug("queryMBeans", + "connectionId=" + connectionId + +", name="+name +", query="+query); + + return cast( + doPrivilegedOperation( + QUERY_MBEANS, + params, + delegationSubject)); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public Set + queryNames(ObjectName name, + MarshalledObject query, + Subject delegationSubject) + throws IOException { + final QueryExp queryValue; + final boolean debug=logger.debugOn(); + + if (debug) logger.debug("queryNames", + "connectionId=" + connectionId + +" unwrapping query with defaultClassLoader."); + + queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject); + + try { + final Object params[] = new Object[] { name, queryValue }; + + if (debug) logger.debug("queryNames", + "connectionId=" + connectionId + +", name="+name +", query="+query); + + return cast( + doPrivilegedOperation( + QUERY_NAMES, + params, + delegationSubject)); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public boolean isRegistered(ObjectName name, + Subject delegationSubject) throws IOException { + try { + final Object params[] = new Object[] { name }; + return ((Boolean) + doPrivilegedOperation( + IS_REGISTERED, + params, + delegationSubject)).booleanValue(); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public Integer getMBeanCount(Subject delegationSubject) + throws IOException { + try { + final Object params[] = new Object[] { }; + + if (logger.debugOn()) logger.debug("getMBeanCount", + "connectionId=" + connectionId); + + return (Integer) + doPrivilegedOperation( + GET_MBEAN_COUNT, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public Object getAttribute(ObjectName name, + String attribute, + Subject delegationSubject) + throws + MBeanException, + AttributeNotFoundException, + InstanceNotFoundException, + ReflectionException, + IOException { + try { + final Object params[] = new Object[] { name, attribute }; + if (logger.debugOn()) logger.debug("getAttribute", + "connectionId=" + connectionId + +", name=" + name + +", attribute="+ attribute); + + return + doPrivilegedOperation( + GET_ATTRIBUTE, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof AttributeNotFoundException) + throw (AttributeNotFoundException) e; + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public AttributeList getAttributes(ObjectName name, + String[] attributes, + Subject delegationSubject) + throws + InstanceNotFoundException, + ReflectionException, + IOException { + try { + final Object params[] = new Object[] { name, attributes }; + + if (logger.debugOn()) logger.debug("getAttributes", + "connectionId=" + connectionId + +", name=" + name + +", attributes="+ strings(attributes)); + + return (AttributeList) + doPrivilegedOperation( + GET_ATTRIBUTES, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public void setAttribute(ObjectName name, + MarshalledObject attribute, + Subject delegationSubject) + throws + InstanceNotFoundException, + AttributeNotFoundException, + InvalidAttributeValueException, + MBeanException, + ReflectionException, + IOException { + final Attribute attr; + final boolean debug=logger.debugOn(); + + if (debug) logger.debug("setAttribute", + "connectionId=" + connectionId + +" unwrapping attribute with MBean extended ClassLoader."); + + attr = unwrap(attribute, + getClassLoaderFor(name), + defaultClassLoader, + Attribute.class, delegationSubject); + + try { + final Object params[] = new Object[] { name, attr }; + + if (debug) logger.debug("setAttribute", + "connectionId=" + connectionId + +", name="+name + +", attribute name="+attr.getName()); + + doPrivilegedOperation( + SET_ATTRIBUTE, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof AttributeNotFoundException) + throw (AttributeNotFoundException) e; + if (e instanceof InvalidAttributeValueException) + throw (InvalidAttributeValueException) e; + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public AttributeList setAttributes(ObjectName name, + MarshalledObject attributes, + Subject delegationSubject) + throws + InstanceNotFoundException, + ReflectionException, + IOException { + final AttributeList attrlist; + final boolean debug=logger.debugOn(); + + if (debug) logger.debug("setAttributes", + "connectionId=" + connectionId + +" unwrapping attributes with MBean extended ClassLoader."); + + attrlist = + unwrap(attributes, + getClassLoaderFor(name), + defaultClassLoader, + AttributeList.class, delegationSubject); + + try { + final Object params[] = new Object[] { name, attrlist }; + + if (debug) logger.debug("setAttributes", + "connectionId=" + connectionId + +", name="+name + +", attribute names="+RMIConnector.getAttributesNames(attrlist)); + + return (AttributeList) + doPrivilegedOperation( + SET_ATTRIBUTES, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public Object invoke(ObjectName name, + String operationName, + MarshalledObject params, + String signature[], + Subject delegationSubject) + throws + InstanceNotFoundException, + MBeanException, + ReflectionException, + IOException { + + checkNonNull("ObjectName", name); + checkNonNull("Operation name", operationName); + + final Object[] values; + final boolean debug=logger.debugOn(); + + if (debug) logger.debug("invoke", + "connectionId=" + connectionId + +" unwrapping params with MBean extended ClassLoader."); + + values = nullIsEmpty(unwrap(params, + getClassLoaderFor(name), + defaultClassLoader, + Object[].class, delegationSubject)); + + try { + final Object params2[] = + new Object[] { name, operationName, values, + nullIsEmpty(signature) }; + + if (debug) logger.debug("invoke", + "connectionId=" + connectionId + +", name="+name + +", operationName="+operationName + +", signature="+strings(signature)); + + return + doPrivilegedOperation( + INVOKE, + params2, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof MBeanException) + throw (MBeanException) e; + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public String getDefaultDomain(Subject delegationSubject) + throws IOException { + try { + final Object params[] = new Object[] { }; + + if (logger.debugOn()) logger.debug("getDefaultDomain", + "connectionId=" + connectionId); + + return (String) + doPrivilegedOperation( + GET_DEFAULT_DOMAIN, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public String[] getDomains(Subject delegationSubject) throws IOException { + try { + final Object params[] = new Object[] { }; + + if (logger.debugOn()) logger.debug("getDomains", + "connectionId=" + connectionId); + + return (String[]) + doPrivilegedOperation( + GET_DOMAINS, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject) + throws + InstanceNotFoundException, + IntrospectionException, + ReflectionException, + IOException { + + checkNonNull("ObjectName", name); + + try { + final Object params[] = new Object[] { name }; + + if (logger.debugOn()) logger.debug("getMBeanInfo", + "connectionId=" + connectionId + +", name="+name); + + return (MBeanInfo) + doPrivilegedOperation( + GET_MBEAN_INFO, + params, + delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof IntrospectionException) + throw (IntrospectionException) e; + if (e instanceof ReflectionException) + throw (ReflectionException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + public boolean isInstanceOf(ObjectName name, + String className, + Subject delegationSubject) + throws InstanceNotFoundException, IOException { + + checkNonNull("ObjectName", name); + + try { + final Object params[] = new Object[] { name, className }; + + if (logger.debugOn()) logger.debug("isInstanceOf", + "connectionId=" + connectionId + +", name="+name + +", className="+className); + + return ((Boolean) + doPrivilegedOperation( + IS_INSTANCE_OF, + params, + delegationSubject)).booleanValue(); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof InstanceNotFoundException) + throw (InstanceNotFoundException) e; + if (e instanceof IOException) + throw (IOException) e; + throw newIOException("Got unexpected server exception: " + e, e); + } + } + + @SuppressWarnings("rawtypes") // MarshalledObject + public Integer[] addNotificationListeners(ObjectName[] names, + MarshalledObject[] filters, + Subject[] delegationSubjects) + throws InstanceNotFoundException, IOException { + + if (names == null || filters == null) { + throw new IllegalArgumentException("Got null arguments."); + } + + Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects : + new Subject[names.length]; + if (names.length != filters.length || filters.length != sbjs.length) { + final String msg = + "The value lengths of 3 parameters are not same."; + throw new IllegalArgumentException(msg); + } + + for (int i=0; i action = + new PrivilegedAction() { + public NotificationResult run() { + return getServerNotifFwd().fetchNotifs(csn, t, mn); + } + }; + if (acc == null) + return action.run(); + else + return AccessController.doPrivileged(action, acc); + } finally { + serverCommunicatorAdmin.rspOutgoing(); + } + } + + /** + *

Returns a string representation of this object. In general, + * the toString method returns a string that + * "textually represents" this object. The result should be a + * concise but informative representation that is easy for a + * person to read.

+ * + * @return a String representation of this object. + **/ + @Override + public String toString() { + return super.toString() + ": connectionId=" + connectionId; + } + + //------------------------------------------------------------------------ + // private classes + //------------------------------------------------------------------------ + + private class PrivilegedOperation + implements PrivilegedExceptionAction { + + public PrivilegedOperation(int operation, Object[] params) { + this.operation = operation; + this.params = params; + } + + public Object run() throws Exception { + return doOperation(operation, params); + } + + private int operation; + private Object[] params; + } + + //------------------------------------------------------------------------ + // private classes + //------------------------------------------------------------------------ + private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin { + public RMIServerCommunicatorAdmin(long timeout) { + super(timeout); + } + + protected void doStop() { + try { + close(); + } catch (IOException ie) { + logger.warning("RMIServerCommunicatorAdmin-doStop", + "Failed to close: " + ie); + logger.debug("RMIServerCommunicatorAdmin-doStop",ie); + } + } + + } + + + //------------------------------------------------------------------------ + // private methods + //------------------------------------------------------------------------ + + private ClassLoader getClassLoader(final ObjectName name) + throws InstanceNotFoundException { + try { + return + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public ClassLoader run() throws InstanceNotFoundException { + return mbeanServer.getClassLoader(name); + } + }, + withPermissions(new MBeanPermission("*", "getClassLoader")) + ); + } catch (PrivilegedActionException pe) { + throw (InstanceNotFoundException) extractException(pe); + } + } + + private ClassLoader getClassLoaderFor(final ObjectName name) + throws InstanceNotFoundException { + try { + return (ClassLoader) + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public Object run() throws InstanceNotFoundException { + return mbeanServer.getClassLoaderFor(name); + } + }, + withPermissions(new MBeanPermission("*", "getClassLoaderFor")) + ); + } catch (PrivilegedActionException pe) { + throw (InstanceNotFoundException) extractException(pe); + } + } + + private Object doPrivilegedOperation(final int operation, + final Object[] params, + final Subject delegationSubject) + throws PrivilegedActionException, IOException { + + serverCommunicatorAdmin.reqIncoming(); + try { + + final AccessControlContext reqACC; + if (delegationSubject == null) + reqACC = acc; + else { + if (subject == null) { + final String msg = + "Subject delegation cannot be enabled unless " + + "an authenticated subject is put in place"; + throw new SecurityException(msg); + } + reqACC = subjectDelegator.delegatedContext( + acc, delegationSubject, removeCallerContext); + } + + PrivilegedOperation op = + new PrivilegedOperation(operation, params); + if (reqACC == null) { + try { + return op.run(); + } catch (Exception e) { + if (e instanceof RuntimeException) + throw (RuntimeException) e; + throw new PrivilegedActionException(e); + } + } else { + return AccessController.doPrivileged(op, reqACC); + } + } catch (Error e) { + throw new JMXServerErrorException(e.toString(),e); + } finally { + serverCommunicatorAdmin.rspOutgoing(); + } + } + + private Object doOperation(int operation, Object[] params) + throws Exception { + + switch (operation) { + + case CREATE_MBEAN: + return mbeanServer.createMBean((String)params[0], + (ObjectName)params[1]); + + case CREATE_MBEAN_LOADER: + return mbeanServer.createMBean((String)params[0], + (ObjectName)params[1], + (ObjectName)params[2]); + + case CREATE_MBEAN_PARAMS: + return mbeanServer.createMBean((String)params[0], + (ObjectName)params[1], + (Object[])params[2], + (String[])params[3]); + + case CREATE_MBEAN_LOADER_PARAMS: + return mbeanServer.createMBean((String)params[0], + (ObjectName)params[1], + (ObjectName)params[2], + (Object[])params[3], + (String[])params[4]); + + case GET_ATTRIBUTE: + return mbeanServer.getAttribute((ObjectName)params[0], + (String)params[1]); + + case GET_ATTRIBUTES: + return mbeanServer.getAttributes((ObjectName)params[0], + (String[])params[1]); + + case GET_DEFAULT_DOMAIN: + return mbeanServer.getDefaultDomain(); + + case GET_DOMAINS: + return mbeanServer.getDomains(); + + case GET_MBEAN_COUNT: + return mbeanServer.getMBeanCount(); + + case GET_MBEAN_INFO: + return mbeanServer.getMBeanInfo((ObjectName)params[0]); + + case GET_OBJECT_INSTANCE: + return mbeanServer.getObjectInstance((ObjectName)params[0]); + + case INVOKE: + return mbeanServer.invoke((ObjectName)params[0], + (String)params[1], + (Object[])params[2], + (String[])params[3]); + + case IS_INSTANCE_OF: + return mbeanServer.isInstanceOf((ObjectName)params[0], + (String)params[1]) + ? Boolean.TRUE : Boolean.FALSE; + + case IS_REGISTERED: + return mbeanServer.isRegistered((ObjectName)params[0]) + ? Boolean.TRUE : Boolean.FALSE; + + case QUERY_MBEANS: + return mbeanServer.queryMBeans((ObjectName)params[0], + (QueryExp)params[1]); + + case QUERY_NAMES: + return mbeanServer.queryNames((ObjectName)params[0], + (QueryExp)params[1]); + + case SET_ATTRIBUTE: + mbeanServer.setAttribute((ObjectName)params[0], + (Attribute)params[1]); + return null; + + case SET_ATTRIBUTES: + return mbeanServer.setAttributes((ObjectName)params[0], + (AttributeList)params[1]); + + case UNREGISTER_MBEAN: + mbeanServer.unregisterMBean((ObjectName)params[0]); + return null; + + case ADD_NOTIFICATION_LISTENERS: + return getServerNotifFwd().addNotificationListener( + (ObjectName)params[0], + (NotificationFilter)params[1]); + + case ADD_NOTIFICATION_LISTENER_OBJECTNAME: + mbeanServer.addNotificationListener((ObjectName)params[0], + (ObjectName)params[1], + (NotificationFilter)params[2], + params[3]); + return null; + + case REMOVE_NOTIFICATION_LISTENER: + getServerNotifFwd().removeNotificationListener( + (ObjectName)params[0], + (Integer[])params[1]); + return null; + + case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME: + mbeanServer.removeNotificationListener((ObjectName)params[0], + (ObjectName)params[1]); + return null; + + case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK: + mbeanServer.removeNotificationListener( + (ObjectName)params[0], + (ObjectName)params[1], + (NotificationFilter)params[2], + params[3]); + return null; + + default: + throw new IllegalArgumentException("Invalid operation"); + } + } + + private static class SetCcl implements PrivilegedExceptionAction { + private final ClassLoader classLoader; + + SetCcl(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public ClassLoader run() { + Thread currentThread = Thread.currentThread(); + ClassLoader old = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(classLoader); + return old; + } + } + + private T unwrap(final MarshalledObject mo, + final ClassLoader cl, + final Class wrappedClass, + Subject delegationSubject) + throws IOException { + if (mo == null) { + return null; + } + try { + final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl)); + try{ + final AccessControlContext reqACC; + if (delegationSubject == null) + reqACC = acc; + else { + if (subject == null) { + final String msg = + "Subject delegation cannot be enabled unless " + + "an authenticated subject is put in place"; + throw new SecurityException(msg); + } + reqACC = subjectDelegator.delegatedContext( + acc, delegationSubject, removeCallerContext); + } + if(reqACC != null){ + return AccessController.doPrivileged( + (PrivilegedExceptionAction) () -> + wrappedClass.cast(mo.get()), reqACC); + }else{ + return wrappedClass.cast(mo.get()); + } + }finally{ + AccessController.doPrivileged(new SetCcl(old)); + } + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) { + throw (IOException) e; + } + if (e instanceof ClassNotFoundException) { + throw new UnmarshalException(e.toString(), e); + } + logger.warning("unwrap", "Failed to unmarshall object: " + e); + logger.debug("unwrap", e); + }catch (ClassNotFoundException ex) { + logger.warning("unwrap", "Failed to unmarshall object: " + ex); + logger.debug("unwrap", ex); + throw new UnmarshalException(ex.toString(), ex); + } + return null; + } + + private T unwrap(final MarshalledObject mo, + final ClassLoader cl1, + final ClassLoader cl2, + final Class wrappedClass, + Subject delegationSubject) + throws IOException { + if (mo == null) { + return null; + } + try { + ClassLoader orderCL = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public ClassLoader run() throws Exception { + return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(), + new OrderClassLoaders(cl1, cl2)); + } + } + ); + return unwrap(mo, orderCL, wrappedClass,delegationSubject); + } catch (PrivilegedActionException pe) { + Exception e = extractException(pe); + if (e instanceof IOException) { + throw (IOException) e; + } + if (e instanceof ClassNotFoundException) { + throw new UnmarshalException(e.toString(), e); + } + logger.warning("unwrap", "Failed to unmarshall object: " + e); + logger.debug("unwrap", e); + } + return null; + } + + /** + * Construct a new IOException with a nested exception. + * The nested exception is set only if JDK {@literal >= 1.4} + */ + private static IOException newIOException(String message, + Throwable cause) { + final IOException x = new IOException(message); + return EnvHelp.initCause(x,cause); + } + + /** + * Iterate until we extract the real exception + * from a stack of PrivilegedActionExceptions. + */ + private static Exception extractException(Exception e) { + while (e instanceof PrivilegedActionException) { + e = ((PrivilegedActionException)e).getException(); + } + return e; + } + + private static final Object[] NO_OBJECTS = new Object[0]; + private static final String[] NO_STRINGS = new String[0]; + + /* + * The JMX spec doesn't explicitly say that a null Object[] or + * String[] in e.g. MBeanServer.invoke is equivalent to an empty + * array, but the RI behaves that way. In the interests of + * maximal interoperability, we make it so even when we're + * connected to some other JMX implementation that might not do + * that. This should be clarified in the next version of JMX. + */ + private static Object[] nullIsEmpty(Object[] array) { + return (array == null) ? NO_OBJECTS : array; + } + + private static String[] nullIsEmpty(String[] array) { + return (array == null) ? NO_STRINGS : array; + } + + /* + * Similarly, the JMX spec says for some but not all methods in + * MBeanServer that take an ObjectName target, that if it's null + * you get this exception. We specify it for all of them, and + * make it so for the ones where it's not specified in JMX even if + * the JMX implementation doesn't do so. + */ + private static void checkNonNull(String what, Object x) { + if (x == null) { + RuntimeException wrapped = + new IllegalArgumentException(what + " must not be null"); + throw new RuntimeOperationsException(wrapped); + } + } + + //------------------------------------------------------------------------ + // private variables + //------------------------------------------------------------------------ + + private final Subject subject; + + private final SubjectDelegator subjectDelegator; + + private final boolean removeCallerContext; + + private final AccessControlContext acc; + + private final RMIServerImpl rmiServer; + + private final MBeanServer mbeanServer; + + private final ClassLoader defaultClassLoader; + + private final ClassLoader defaultContextClassLoader; + + private final ClassLoaderWithRepository classLoaderWithRepository; + + private boolean terminated = false; + + private final String connectionId; + + private final ServerCommunicatorAdmin serverCommunicatorAdmin; + + // Method IDs for doOperation + //--------------------------- + + private final static int + ADD_NOTIFICATION_LISTENERS = 1; + private final static int + ADD_NOTIFICATION_LISTENER_OBJECTNAME = 2; + private final static int + CREATE_MBEAN = 3; + private final static int + CREATE_MBEAN_PARAMS = 4; + private final static int + CREATE_MBEAN_LOADER = 5; + private final static int + CREATE_MBEAN_LOADER_PARAMS = 6; + private final static int + GET_ATTRIBUTE = 7; + private final static int + GET_ATTRIBUTES = 8; + private final static int + GET_DEFAULT_DOMAIN = 9; + private final static int + GET_DOMAINS = 10; + private final static int + GET_MBEAN_COUNT = 11; + private final static int + GET_MBEAN_INFO = 12; + private final static int + GET_OBJECT_INSTANCE = 13; + private final static int + INVOKE = 14; + private final static int + IS_INSTANCE_OF = 15; + private final static int + IS_REGISTERED = 16; + private final static int + QUERY_MBEANS = 17; + private final static int + QUERY_NAMES = 18; + private final static int + REMOVE_NOTIFICATION_LISTENER = 19; + private final static int + REMOVE_NOTIFICATION_LISTENER_OBJECTNAME = 20; + private final static int + REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 21; + private final static int + SET_ATTRIBUTE = 22; + private final static int + SET_ATTRIBUTES = 23; + private final static int + UNREGISTER_MBEAN = 24; + + // SERVER NOTIFICATION + //-------------------- + + private ServerNotifForwarder serverNotifForwarder; + private Map env; + + // TRACES & DEBUG + //--------------- + + private static String objects(final Object[] objs) { + if (objs == null) + return "null"; + else + return Arrays.asList(objs).toString(); + } + + private static String strings(final String[] strs) { + return objects(strs); + } + + private static final ClassLogger logger = + new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl"); + + private static final class CombinedClassLoader extends ClassLoader { + + private final static class ClassLoaderWrapper extends ClassLoader { + ClassLoaderWrapper(ClassLoader cl) { + super(cl); + } + + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + return super.loadClass(name, resolve); + } + }; + + final ClassLoaderWrapper defaultCL; + + private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) { + super(parent); + this.defaultCL = new ClassLoaderWrapper(defaultCL); + } + + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + ReflectUtil.checkPackageAccess(name); + try { + super.loadClass(name, resolve); + } catch(Exception e) { + for(Throwable t = e; t != null; t = t.getCause()) { + if(t instanceof SecurityException) { + throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e); + } + } + } + final Class cl = defaultCL.loadClass(name, resolve); + return cl; + } + + } +}