0N/A/*
3038N/A * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.management.remote.rmi;
0N/A
686N/Aimport com.sun.jmx.mbeanserver.Util;
0N/Aimport com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
0N/Aimport com.sun.jmx.remote.internal.ClientListenerInfo;
0N/Aimport com.sun.jmx.remote.internal.ClientNotifForwarder;
0N/Aimport com.sun.jmx.remote.internal.ProxyRef;
1801N/Aimport com.sun.jmx.remote.internal.IIOPHelper;
0N/Aimport com.sun.jmx.remote.util.ClassLogger;
0N/Aimport com.sun.jmx.remote.util.EnvHelp;
0N/Aimport java.io.ByteArrayInputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.InputStream;
0N/Aimport java.io.InvalidObjectException;
0N/Aimport java.io.NotSerializableException;
0N/Aimport java.io.ObjectInputStream;
0N/Aimport java.io.ObjectStreamClass;
0N/Aimport java.io.Serializable;
0N/Aimport java.io.WriteAbortedException;
0N/Aimport java.lang.ref.WeakReference;
0N/Aimport java.lang.reflect.Constructor;
0N/Aimport java.lang.reflect.InvocationHandler;
0N/Aimport java.lang.reflect.InvocationTargetException;
0N/Aimport java.lang.reflect.Proxy;
0N/Aimport java.net.MalformedURLException;
0N/Aimport java.rmi.MarshalException;
0N/Aimport java.rmi.MarshalledObject;
0N/Aimport java.rmi.NoSuchObjectException;
0N/Aimport java.rmi.Remote;
0N/Aimport java.rmi.ServerException;
0N/Aimport java.rmi.UnmarshalException;
0N/Aimport java.rmi.server.RMIClientSocketFactory;
0N/Aimport java.rmi.server.RemoteObject;
0N/Aimport java.rmi.server.RemoteObjectInvocationHandler;
0N/Aimport java.rmi.server.RemoteRef;
0N/Aimport java.security.AccessController;
0N/Aimport java.security.PrivilegedAction;
0N/Aimport java.security.PrivilegedExceptionAction;
0N/Aimport java.security.ProtectionDomain;
0N/Aimport java.util.Arrays;
0N/Aimport java.util.Collections;
0N/Aimport java.util.HashMap;
0N/Aimport java.util.Map;
0N/Aimport java.util.Properties;
0N/Aimport java.util.Set;
0N/Aimport java.util.WeakHashMap;
0N/Aimport javax.management.Attribute;
0N/Aimport javax.management.AttributeList;
0N/Aimport javax.management.AttributeNotFoundException;
0N/Aimport javax.management.InstanceAlreadyExistsException;
0N/Aimport javax.management.InstanceNotFoundException;
0N/Aimport javax.management.IntrospectionException;
0N/Aimport javax.management.InvalidAttributeValueException;
0N/Aimport javax.management.ListenerNotFoundException;
0N/Aimport javax.management.MBeanException;
0N/Aimport javax.management.MBeanInfo;
0N/Aimport javax.management.MBeanRegistrationException;
0N/Aimport javax.management.MBeanServerConnection;
0N/Aimport javax.management.MBeanServerDelegate;
0N/Aimport javax.management.MBeanServerNotification;
0N/Aimport javax.management.NotCompliantMBeanException;
0N/Aimport javax.management.Notification;
0N/Aimport javax.management.NotificationBroadcasterSupport;
0N/Aimport javax.management.NotificationFilter;
0N/Aimport javax.management.NotificationFilterSupport;
0N/Aimport javax.management.NotificationListener;
0N/Aimport javax.management.ObjectInstance;
0N/Aimport javax.management.ObjectName;
0N/Aimport javax.management.QueryExp;
0N/Aimport javax.management.ReflectionException;
0N/Aimport javax.management.remote.JMXConnectionNotification;
0N/Aimport javax.management.remote.JMXConnector;
0N/Aimport javax.management.remote.JMXConnectorFactory;
0N/Aimport javax.management.remote.JMXServiceURL;
0N/Aimport javax.management.remote.NotificationResult;
0N/Aimport javax.management.remote.JMXAddressable;
0N/Aimport javax.naming.InitialContext;
0N/Aimport javax.naming.NamingException;
0N/Aimport javax.rmi.ssl.SslRMIClientSocketFactory;
0N/Aimport javax.security.auth.Subject;
6298N/Aimport sun.reflect.misc.ReflectUtil;
0N/Aimport sun.rmi.server.UnicastRef2;
0N/Aimport sun.rmi.transport.LiveRef;
0N/A
0N/A/**
0N/A * <p>A connection to a remote RMI connector. Usually, such
0N/A * connections are made using {@link
0N/A * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
0N/A * However, specialized applications can use this class directly, for
0N/A * example with an {@link RMIServer} stub obtained without going
0N/A * through JNDI.</p>
0N/A *
0N/A * @since 1.5
0N/A */
0N/Apublic class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
0N/A
0N/A private static final ClassLogger logger =
699N/A new ClassLogger("javax.management.remote.rmi", "RMIConnector");
0N/A
0N/A private static final long serialVersionUID = 817323035842634473L;
0N/A
0N/A private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
699N/A Map<String, ?> environment) {
0N/A if (rmiServer == null && address == null) throw new
699N/A IllegalArgumentException("rmiServer and jmxServiceURL both null");
0N/A
0N/A initTransients();
0N/A
0N/A this.rmiServer = rmiServer;
0N/A this.jmxServiceURL = address;
0N/A if (environment == null) {
0N/A this.env = Collections.emptyMap();
0N/A } else {
0N/A EnvHelp.checkAttributes(environment);
0N/A this.env = Collections.unmodifiableMap(environment);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * <p>Constructs an <code>RMIConnector</code> that will connect
0N/A * the RMI connector server with the given address.</p>
0N/A *
0N/A * <p>The address can refer directly to the connector server,
0N/A * using one of the following syntaxes:</p>
0N/A *
0N/A * <pre>
0N/A * service:jmx:rmi://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
0N/A * service:jmx:iiop://<em>[host[:port]]</em>/ior/<em>encoded-IOR</em>
0N/A * </pre>
0N/A *
0N/A * <p>(Here, the square brackets <code>[]</code> are not part of the
0N/A * address but indicate that the host and port are optional.)</p>
0N/A *
0N/A * <p>The address can instead indicate where to find an RMI stub
0N/A * through JNDI, using one of the following syntaxes:</p>
0N/A *
0N/A * <pre>
0N/A * service:jmx:rmi://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
0N/A * service:jmx:iiop://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
0N/A * </pre>
0N/A *
0N/A * <p>An implementation may also recognize additional address
0N/A * syntaxes, for example:</p>
0N/A *
0N/A * <pre>
0N/A * service:jmx:iiop://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
0N/A * </pre>
0N/A *
0N/A * @param url the address of the RMI connector server.
0N/A *
0N/A * @param environment additional attributes specifying how to make
0N/A * the connection. For JNDI-based addresses, these attributes can
0N/A * usefully include JNDI attributes recognized by {@link
0N/A * InitialContext#InitialContext(Hashtable) InitialContext}. This
0N/A * parameter can be null, which is equivalent to an empty Map.
0N/A *
0N/A * @exception IllegalArgumentException if <code>url</code>
0N/A * is null.
0N/A */
0N/A public RMIConnector(JMXServiceURL url, Map<String,?> environment) {
0N/A this(null, url, environment);
0N/A }
0N/A
0N/A /**
0N/A * <p>Constructs an <code>RMIConnector</code> using the given RMI stub.
0N/A *
0N/A * @param rmiServer an RMI stub representing the RMI connector server.
0N/A * @param environment additional attributes specifying how to make
0N/A * the connection. This parameter can be null, which is
0N/A * equivalent to an empty Map.
0N/A *
0N/A * @exception IllegalArgumentException if <code>rmiServer</code>
0N/A * is null.
0N/A */
0N/A public RMIConnector(RMIServer rmiServer, Map<String,?> environment) {
0N/A this(rmiServer, null, environment);
0N/A }
0N/A
0N/A /**
0N/A * <p>Returns a string representation of this object. In general,
0N/A * the <code>toString</code> method returns a string that
0N/A * "textually represents" this object. The result should be a
0N/A * concise but informative representation that is easy for a
0N/A * person to read.</p>
0N/A *
0N/A * @return a String representation of this object.
0N/A **/
1790N/A @Override
0N/A public String toString() {
0N/A final StringBuilder b = new StringBuilder(this.getClass().getName());
0N/A b.append(":");
0N/A if (rmiServer != null) {
0N/A b.append(" rmiServer=").append(rmiServer.toString());
0N/A }
0N/A if (jmxServiceURL != null) {
0N/A if (rmiServer!=null) b.append(",");
0N/A b.append(" jmxServiceURL=").append(jmxServiceURL.toString());
0N/A }
0N/A return b.toString();
0N/A }
0N/A
0N/A /**
0N/A * <p>The address of this connector.</p>
0N/A *
0N/A * @return the address of this connector, or null if it
0N/A * does not have one.
0N/A *
0N/A * @since 1.6
0N/A */
0N/A public JMXServiceURL getAddress() {
0N/A return jmxServiceURL;
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A // implements JMXConnector interface
0N/A //--------------------------------------------------------------------
0N/A public void connect() throws IOException {
0N/A connect(null);
0N/A }
0N/A
0N/A public synchronized void connect(Map<String,?> environment)
699N/A throws IOException {
0N/A final boolean tracing = logger.traceOn();
0N/A String idstr = (tracing?"["+this.toString()+"]":null);
0N/A
0N/A if (terminated) {
0N/A logger.trace("connect",idstr + " already closed.");
0N/A throw new IOException("Connector closed");
0N/A }
0N/A if (connected) {
0N/A logger.trace("connect",idstr + " already connected.");
0N/A return;
0N/A }
0N/A
0N/A try {
0N/A if (tracing) logger.trace("connect",idstr + " connecting...");
0N/A
0N/A final Map<String, Object> usemap =
699N/A new HashMap<String, Object>((this.env==null) ?
699N/A Collections.<String, Object>emptyMap() : this.env);
0N/A
0N/A
0N/A if (environment != null) {
0N/A EnvHelp.checkAttributes(environment);
0N/A usemap.putAll(environment);
0N/A }
0N/A
0N/A // Get RMIServer stub from directory or URL encoding if needed.
0N/A if (tracing) logger.trace("connect",idstr + " finding stub...");
0N/A RMIServer stub = (rmiServer!=null)?rmiServer:
0N/A findRMIServer(jmxServiceURL, usemap);
0N/A
0N/A // Check for secure RMIServer stub if the corresponding
0N/A // client-side environment property is set to "true".
0N/A //
5395N/A String stringBoolean = (String) usemap.get("jmx.remote.x.check.stub");
5395N/A boolean checkStub = EnvHelp.computeBooleanFromString(stringBoolean);
5395N/A
0N/A if (checkStub) checkStub(stub, rmiServerImplStubClass);
0N/A
0N/A // Connect IIOP Stub if needed.
0N/A if (tracing) logger.trace("connect",idstr + " connecting stub...");
0N/A stub = connectStub(stub,usemap);
0N/A idstr = (tracing?"["+this.toString()+"]":null);
0N/A
0N/A // Calling newClient on the RMIServer stub.
0N/A if (tracing)
0N/A logger.trace("connect",idstr + " getting connection...");
0N/A Object credentials = usemap.get(CREDENTIALS);
3038N/A
3038N/A try {
3038N/A connection = getConnection(stub, credentials, checkStub);
3038N/A } catch (java.rmi.RemoteException re) {
3038N/A if (jmxServiceURL != null) {
3038N/A final String pro = jmxServiceURL.getProtocol();
3038N/A final String path = jmxServiceURL.getURLPath();
3038N/A
3038N/A if ("rmi".equals(pro) &&
3038N/A path.startsWith("/jndi/iiop:")) {
3038N/A MalformedURLException mfe = new MalformedURLException(
3038N/A "Protocol is rmi but JNDI scheme is iiop: " + jmxServiceURL);
3038N/A mfe.initCause(re);
3038N/A throw mfe;
3038N/A }
3038N/A }
3038N/A throw re;
3038N/A }
0N/A
0N/A // Always use one of:
0N/A // ClassLoader provided in Map at connect time,
0N/A // or contextClassLoader at connect time.
0N/A if (tracing)
0N/A logger.trace("connect",idstr + " getting class loader...");
0N/A defaultClassLoader = EnvHelp.resolveClientClassLoader(usemap);
0N/A
0N/A usemap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
699N/A defaultClassLoader);
0N/A
0N/A rmiNotifClient = new RMINotifClient(defaultClassLoader, usemap);
0N/A
0N/A env = usemap;
0N/A final long checkPeriod = EnvHelp.getConnectionCheckPeriod(usemap);
0N/A communicatorAdmin = new RMIClientCommunicatorAdmin(checkPeriod);
0N/A
0N/A connected = true;
0N/A
0N/A // The connectionId variable is used in doStart(), when
0N/A // reconnecting, to identify the "old" connection.
0N/A //
0N/A connectionId = getConnectionId();
0N/A
0N/A Notification connectedNotif =
699N/A new JMXConnectionNotification(JMXConnectionNotification.OPENED,
699N/A this,
699N/A connectionId,
699N/A clientNotifSeqNo++,
699N/A "Successful connection",
699N/A null);
0N/A sendNotification(connectedNotif);
0N/A
0N/A if (tracing) logger.trace("connect",idstr + " done...");
0N/A } catch (IOException e) {
0N/A if (tracing)
0N/A logger.trace("connect",idstr + " failed to connect: " + e);
0N/A throw e;
0N/A } catch (RuntimeException e) {
0N/A if (tracing)
0N/A logger.trace("connect",idstr + " failed to connect: " + e);
0N/A throw e;
0N/A } catch (NamingException e) {
0N/A final String msg = "Failed to retrieve RMIServer stub: " + e;
0N/A if (tracing) logger.trace("connect",idstr + " " + msg);
0N/A throw EnvHelp.initCause(new IOException(msg),e);
0N/A }
0N/A }
0N/A
0N/A public synchronized String getConnectionId() throws IOException {
0N/A if (terminated || !connected) {
0N/A if (logger.traceOn())
0N/A logger.trace("getConnectionId","["+this.toString()+
699N/A "] not connected.");
0N/A
0N/A throw new IOException("Not connected");
0N/A }
0N/A
0N/A // we do a remote call to have an IOException if the connection is broken.
0N/A // see the bug 4939578
0N/A return connection.getConnectionId();
0N/A }
0N/A
0N/A public synchronized MBeanServerConnection getMBeanServerConnection()
699N/A throws IOException {
0N/A return getMBeanServerConnection(null);
0N/A }
0N/A
0N/A public synchronized MBeanServerConnection
699N/A getMBeanServerConnection(Subject delegationSubject)
0N/A throws IOException {
0N/A
0N/A if (terminated) {
0N/A if (logger.traceOn())
0N/A logger.trace("getMBeanServerConnection","[" + this.toString() +
699N/A "] already closed.");
0N/A throw new IOException("Connection closed");
0N/A } else if (!connected) {
0N/A if (logger.traceOn())
0N/A logger.trace("getMBeanServerConnection","[" + this.toString() +
699N/A "] is not connected.");
0N/A throw new IOException("Not connected");
0N/A }
0N/A
469N/A MBeanServerConnection rmbsc = rmbscMap.get(delegationSubject);
469N/A if (rmbsc != null) {
469N/A return rmbsc;
469N/A }
469N/A
469N/A rmbsc = new RemoteMBeanServerConnection(delegationSubject);
469N/A rmbscMap.put(delegationSubject, rmbsc);
469N/A return rmbsc;
469N/A }
469N/A
0N/A public void
699N/A addConnectionNotificationListener(NotificationListener listener,
699N/A NotificationFilter filter,
699N/A Object handback) {
0N/A if (listener == null)
0N/A throw new NullPointerException("listener");
0N/A connectionBroadcaster.addNotificationListener(listener, filter,
699N/A handback);
0N/A }
0N/A
0N/A public void
699N/A removeConnectionNotificationListener(NotificationListener listener)
0N/A throws ListenerNotFoundException {
0N/A if (listener == null)
0N/A throw new NullPointerException("listener");
0N/A connectionBroadcaster.removeNotificationListener(listener);
0N/A }
0N/A
0N/A public void
699N/A removeConnectionNotificationListener(NotificationListener listener,
699N/A NotificationFilter filter,
699N/A Object handback)
0N/A throws ListenerNotFoundException {
0N/A if (listener == null)
0N/A throw new NullPointerException("listener");
0N/A connectionBroadcaster.removeNotificationListener(listener, filter,
699N/A handback);
0N/A }
0N/A
0N/A private void sendNotification(Notification n) {
0N/A connectionBroadcaster.sendNotification(n);
0N/A }
0N/A
0N/A public synchronized void close() throws IOException {
0N/A close(false);
0N/A }
0N/A
0N/A // allows to do close after setting the flag "terminated" to true.
0N/A // It is necessary to avoid a deadlock, see 6296324
0N/A private synchronized void close(boolean intern) throws IOException {
0N/A final boolean tracing = logger.traceOn();
0N/A final boolean debug = logger.debugOn();
0N/A final String idstr = (tracing?"["+this.toString()+"]":null);
0N/A
0N/A if (!intern) {
0N/A // Return if already cleanly closed.
0N/A //
0N/A if (terminated) {
0N/A if (closeException == null) {
0N/A if (tracing) logger.trace("close",idstr + " already closed.");
0N/A return;
0N/A }
0N/A } else {
0N/A terminated = true;
0N/A }
0N/A }
0N/A
0N/A if (closeException != null && tracing) {
0N/A // Already closed, but not cleanly. Attempt again.
0N/A //
0N/A if (tracing) {
0N/A logger.trace("close",idstr + " had failed: " + closeException);
0N/A logger.trace("close",idstr + " attempting to close again.");
0N/A }
0N/A }
0N/A
0N/A String savedConnectionId = null;
0N/A if (connected) {
0N/A savedConnectionId = connectionId;
0N/A }
0N/A
0N/A closeException = null;
0N/A
0N/A if (tracing) logger.trace("close",idstr + " closing.");
0N/A
0N/A if (communicatorAdmin != null) {
0N/A communicatorAdmin.terminate();
0N/A }
0N/A
0N/A if (rmiNotifClient != null) {
0N/A try {
0N/A rmiNotifClient.terminate();
0N/A if (tracing) logger.trace("close",idstr +
699N/A " RMI Notification client terminated.");
0N/A } catch (RuntimeException x) {
0N/A closeException = x;
0N/A if (tracing) logger.trace("close",idstr +
699N/A " Failed to terminate RMI Notification client: " + x);
0N/A if (debug) logger.debug("close",x);
0N/A }
0N/A }
0N/A
0N/A if (connection != null) {
0N/A try {
0N/A connection.close();
0N/A if (tracing) logger.trace("close",idstr + " closed.");
0N/A } catch (NoSuchObjectException nse) {
0N/A // OK, the server maybe closed itself.
0N/A } catch (IOException e) {
0N/A closeException = e;
0N/A if (tracing) logger.trace("close",idstr +
699N/A " Failed to close RMIServer: " + e);
0N/A if (debug) logger.debug("close",e);
0N/A }
0N/A }
0N/A
0N/A // Clean up MBeanServerConnection table
0N/A //
0N/A rmbscMap.clear();
0N/A
0N/A /* Send notification of closure. We don't do this if the user
0N/A * never called connect() on the connector, because there's no
0N/A * connection id in that case. */
0N/A
0N/A if (savedConnectionId != null) {
0N/A Notification closedNotif =
699N/A new JMXConnectionNotification(JMXConnectionNotification.CLOSED,
699N/A this,
699N/A savedConnectionId,
699N/A clientNotifSeqNo++,
699N/A "Client has been closed",
699N/A null);
0N/A sendNotification(closedNotif);
0N/A }
0N/A
0N/A // throw exception if needed
0N/A //
0N/A if (closeException != null) {
0N/A if (tracing) logger.trace("close",idstr + " failed to close: " +
699N/A closeException);
0N/A if (closeException instanceof IOException)
0N/A throw (IOException) closeException;
0N/A if (closeException instanceof RuntimeException)
0N/A throw (RuntimeException) closeException;
0N/A final IOException x =
699N/A new IOException("Failed to close: " + closeException);
0N/A throw EnvHelp.initCause(x,closeException);
0N/A }
0N/A }
0N/A
0N/A // added for re-connection
0N/A private Integer addListenerWithSubject(ObjectName name,
686N/A MarshalledObject<NotificationFilter> filter,
0N/A Subject delegationSubject,
0N/A boolean reconnect)
0N/A throws InstanceNotFoundException, IOException {
0N/A
0N/A final boolean debug = logger.debugOn();
0N/A if (debug)
0N/A logger.debug("addListenerWithSubject",
699N/A "(ObjectName,MarshalledObject,Subject)");
0N/A
0N/A final ObjectName[] names = new ObjectName[] {name};
686N/A final MarshalledObject<NotificationFilter>[] filters =
686N/A Util.cast(new MarshalledObject<?>[] {filter});
0N/A final Subject[] delegationSubjects = new Subject[] {
0N/A delegationSubject
0N/A };
0N/A
0N/A final Integer[] listenerIDs =
699N/A addListenersWithSubjects(names,filters,delegationSubjects,
699N/A reconnect);
0N/A
0N/A if (debug) logger.debug("addListenerWithSubject","listenerID="
699N/A + listenerIDs[0]);
0N/A return listenerIDs[0];
0N/A }
0N/A
0N/A // added for re-connection
0N/A private Integer[] addListenersWithSubjects(ObjectName[] names,
686N/A MarshalledObject<NotificationFilter>[] filters,
0N/A Subject[] delegationSubjects,
0N/A boolean reconnect)
0N/A throws InstanceNotFoundException, IOException {
0N/A
0N/A final boolean debug = logger.debugOn();
0N/A if (debug)
699N/A logger.debug("addListenersWithSubjects",
699N/A "(ObjectName[],MarshalledObject[],Subject[])");
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A Integer[] listenerIDs = null;
0N/A
0N/A try {
0N/A listenerIDs = connection.addNotificationListeners(names,
699N/A filters,
699N/A delegationSubjects);
0N/A } catch (NoSuchObjectException noe) {
0N/A // maybe reconnect
0N/A if (reconnect) {
0N/A communicatorAdmin.gotIOException(noe);
0N/A
0N/A listenerIDs = connection.addNotificationListeners(names,
699N/A filters,
699N/A delegationSubjects);
0N/A } else {
0N/A throw noe;
0N/A }
0N/A } catch (IOException ioe) {
0N/A // send a failed notif if necessary
0N/A communicatorAdmin.gotIOException(ioe);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A
0N/A if (debug) logger.debug("addListenersWithSubjects","registered "
469N/A + ((listenerIDs==null)?0:listenerIDs.length)
469N/A + " listener(s)");
0N/A return listenerIDs;
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A // Implementation of MBeanServerConnection
0N/A //--------------------------------------------------------------------
469N/A private class RemoteMBeanServerConnection implements MBeanServerConnection {
469N/A private Subject delegationSubject;
0N/A
0N/A public RemoteMBeanServerConnection() {
0N/A this(null);
0N/A }
0N/A
0N/A public RemoteMBeanServerConnection(Subject delegationSubject) {
0N/A this.delegationSubject = delegationSubject;
0N/A }
0N/A
0N/A public ObjectInstance createMBean(String className,
699N/A ObjectName name)
0N/A throws ReflectionException,
699N/A InstanceAlreadyExistsException,
699N/A MBeanRegistrationException,
699N/A MBeanException,
699N/A NotCompliantMBeanException,
699N/A IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("createMBean(String,ObjectName)",
699N/A "className=" + className + ", name=" +
699N/A name);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.createMBean(className,
699N/A name,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.createMBean(className,
699N/A name,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public ObjectInstance createMBean(String className,
699N/A ObjectName name,
699N/A ObjectName loaderName)
699N/A throws ReflectionException,
699N/A InstanceAlreadyExistsException,
699N/A MBeanRegistrationException,
699N/A MBeanException,
699N/A NotCompliantMBeanException,
699N/A InstanceNotFoundException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn())
0N/A logger.debug("createMBean(String,ObjectName,ObjectName)",
699N/A "className=" + className + ", name="
699N/A + name + ", loaderName="
699N/A + loaderName + ")");
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.createMBean(className,
699N/A name,
699N/A loaderName,
699N/A delegationSubject);
0N/A
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.createMBean(className,
699N/A name,
699N/A loaderName,
699N/A delegationSubject);
0N/A
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public ObjectInstance createMBean(String className,
699N/A ObjectName name,
699N/A Object params[],
699N/A String signature[])
0N/A throws ReflectionException,
699N/A InstanceAlreadyExistsException,
699N/A MBeanRegistrationException,
699N/A MBeanException,
699N/A NotCompliantMBeanException,
699N/A IOException {
0N/A if (logger.debugOn())
699N/A logger.debug("createMBean(String,ObjectName,Object[],String[])",
699N/A "className=" + className + ", name="
699N/A + name + ", params="
699N/A + objects(params) + ", signature="
699N/A + strings(signature));
0N/A
0N/A final MarshalledObject<Object[]> sParams =
0N/A new MarshalledObject<Object[]>(params);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.createMBean(className,
699N/A name,
699N/A sParams,
699N/A signature,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.createMBean(className,
699N/A name,
699N/A sParams,
699N/A signature,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public ObjectInstance createMBean(String className,
699N/A ObjectName name,
699N/A ObjectName loaderName,
699N/A Object params[],
699N/A String signature[])
0N/A throws ReflectionException,
699N/A InstanceAlreadyExistsException,
699N/A MBeanRegistrationException,
699N/A MBeanException,
699N/A NotCompliantMBeanException,
699N/A InstanceNotFoundException,
699N/A IOException {
0N/A if (logger.debugOn()) logger.debug(
699N/A "createMBean(String,ObjectName,ObjectName,Object[],String[])",
699N/A "className=" + className + ", name=" + name + ", loaderName="
699N/A + loaderName + ", params=" + objects(params)
699N/A + ", signature=" + strings(signature));
0N/A
0N/A final MarshalledObject<Object[]> sParams =
0N/A new MarshalledObject<Object[]>(params);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.createMBean(className,
699N/A name,
699N/A loaderName,
699N/A sParams,
699N/A signature,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.createMBean(className,
699N/A name,
699N/A loaderName,
699N/A sParams,
699N/A signature,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public void unregisterMBean(ObjectName name)
699N/A throws InstanceNotFoundException,
699N/A MBeanRegistrationException,
699N/A IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("unregisterMBean", "name=" + name);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A connection.unregisterMBean(name, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.unregisterMBean(name, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public ObjectInstance getObjectInstance(ObjectName name)
699N/A throws InstanceNotFoundException,
699N/A IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("getObjectInstance", "name=" + name);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getObjectInstance(name, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getObjectInstance(name, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public Set<ObjectInstance> queryMBeans(ObjectName name,
699N/A QueryExp query)
699N/A throws IOException {
0N/A if (logger.debugOn()) logger.debug("queryMBeans",
699N/A "name=" + name + ", query=" + query);
0N/A
0N/A final MarshalledObject<QueryExp> sQuery =
0N/A new MarshalledObject<QueryExp>(query);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.queryMBeans(name, sQuery, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.queryMBeans(name, sQuery, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public Set<ObjectName> queryNames(ObjectName name,
699N/A QueryExp query)
0N/A throws IOException {
0N/A if (logger.debugOn()) logger.debug("queryNames",
699N/A "name=" + name + ", query=" + query);
0N/A
0N/A final MarshalledObject<QueryExp> sQuery =
0N/A new MarshalledObject<QueryExp>(query);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.queryNames(name, sQuery, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.queryNames(name, sQuery, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public boolean isRegistered(ObjectName name)
699N/A throws IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("isRegistered", "name=" + name);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.isRegistered(name, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.isRegistered(name, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public Integer getMBeanCount()
699N/A throws IOException {
0N/A if (logger.debugOn()) logger.debug("getMBeanCount", "");
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getMBeanCount(delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getMBeanCount(delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public Object getAttribute(ObjectName name,
699N/A String attribute)
0N/A throws MBeanException,
699N/A AttributeNotFoundException,
699N/A InstanceNotFoundException,
699N/A ReflectionException,
699N/A IOException {
0N/A if (logger.debugOn()) logger.debug("getAttribute",
699N/A "name=" + name + ", attribute="
699N/A + attribute);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getAttribute(name,
699N/A attribute,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getAttribute(name,
699N/A attribute,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public AttributeList getAttributes(ObjectName name,
699N/A String[] attributes)
0N/A throws InstanceNotFoundException,
699N/A ReflectionException,
699N/A IOException {
0N/A if (logger.debugOn()) logger.debug("getAttributes",
699N/A "name=" + name + ", attributes="
699N/A + strings(attributes));
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getAttributes(name,
699N/A attributes,
699N/A delegationSubject);
0N/A
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getAttributes(name,
699N/A attributes,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A
0N/A public void setAttribute(ObjectName name,
699N/A Attribute attribute)
699N/A throws InstanceNotFoundException,
699N/A AttributeNotFoundException,
699N/A InvalidAttributeValueException,
699N/A MBeanException,
699N/A ReflectionException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn()) logger.debug("setAttribute",
699N/A "name=" + name + ", attribute="
699N/A + attribute);
0N/A
0N/A final MarshalledObject<Attribute> sAttribute =
699N/A new MarshalledObject<Attribute>(attribute);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A connection.setAttribute(name, sAttribute, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.setAttribute(name, sAttribute, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public AttributeList setAttributes(ObjectName name,
699N/A AttributeList attributes)
699N/A throws InstanceNotFoundException,
699N/A ReflectionException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn()) logger.debug("setAttributes",
699N/A "name=" + name + ", attributes="
699N/A + attributes);
0N/A
0N/A final MarshalledObject<AttributeList> sAttributes =
699N/A new MarshalledObject<AttributeList>(attributes);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.setAttributes(name,
699N/A sAttributes,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.setAttributes(name,
699N/A sAttributes,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A
0N/A public Object invoke(ObjectName name,
699N/A String operationName,
699N/A Object params[],
699N/A String signature[])
0N/A throws InstanceNotFoundException,
699N/A MBeanException,
699N/A ReflectionException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn()) logger.debug("invoke",
699N/A "name=" + name
699N/A + ", operationName=" + operationName
699N/A + ", params=" + objects(params)
699N/A + ", signature=" + strings(signature));
0N/A
0N/A final MarshalledObject<Object[]> sParams =
0N/A new MarshalledObject<Object[]>(params);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.invoke(name,
699N/A operationName,
699N/A sParams,
699N/A signature,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.invoke(name,
699N/A operationName,
699N/A sParams,
699N/A signature,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A
0N/A public String getDefaultDomain()
699N/A throws IOException {
0N/A if (logger.debugOn()) logger.debug("getDefaultDomain", "");
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getDefaultDomain(delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getDefaultDomain(delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public String[] getDomains() throws IOException {
0N/A if (logger.debugOn()) logger.debug("getDomains", "");
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getDomains(delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getDomains(delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public MBeanInfo getMBeanInfo(ObjectName name)
699N/A throws InstanceNotFoundException,
699N/A IntrospectionException,
699N/A ReflectionException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn()) logger.debug("getMBeanInfo", "name=" + name);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.getMBeanInfo(name, delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.getMBeanInfo(name, delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A
0N/A public boolean isInstanceOf(ObjectName name,
699N/A String className)
0N/A throws InstanceNotFoundException,
699N/A IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("isInstanceOf", "name=" + name +
699N/A ", className=" + className);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A return connection.isInstanceOf(name,
699N/A className,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A return connection.isInstanceOf(name,
699N/A className,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public void addNotificationListener(ObjectName name,
699N/A ObjectName listener,
699N/A NotificationFilter filter,
699N/A Object handback)
0N/A throws InstanceNotFoundException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn())
0N/A logger.debug("addNotificationListener" +
699N/A "(ObjectName,ObjectName,NotificationFilter,Object)",
699N/A "name=" + name + ", listener=" + listener
699N/A + ", filter=" + filter + ", handback=" + handback);
0N/A
0N/A final MarshalledObject<NotificationFilter> sFilter =
0N/A new MarshalledObject<NotificationFilter>(filter);
0N/A final MarshalledObject<Object> sHandback =
0N/A new MarshalledObject<Object>(handback);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A connection.addNotificationListener(name,
699N/A listener,
699N/A sFilter,
699N/A sHandback,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.addNotificationListener(name,
699N/A listener,
699N/A sFilter,
699N/A sHandback,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public void removeNotificationListener(ObjectName name,
699N/A ObjectName listener)
0N/A throws InstanceNotFoundException,
699N/A ListenerNotFoundException,
699N/A IOException {
0N/A
0N/A if (logger.debugOn()) logger.debug("removeNotificationListener" +
699N/A "(ObjectName,ObjectName)",
699N/A "name=" + name
699N/A + ", listener=" + listener);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A connection.removeNotificationListener(name,
699N/A listener,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.removeNotificationListener(name,
699N/A listener,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A public void removeNotificationListener(ObjectName name,
699N/A ObjectName listener,
699N/A NotificationFilter filter,
699N/A Object handback)
0N/A throws InstanceNotFoundException,
699N/A ListenerNotFoundException,
699N/A IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("removeNotificationListener" +
699N/A "(ObjectName,ObjectName,NotificationFilter,Object)",
699N/A "name=" + name
699N/A + ", listener=" + listener
699N/A + ", filter=" + filter
699N/A + ", handback=" + handback);
0N/A
0N/A final MarshalledObject<NotificationFilter> sFilter =
0N/A new MarshalledObject<NotificationFilter>(filter);
0N/A final MarshalledObject<Object> sHandback =
0N/A new MarshalledObject<Object>(handback);
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A connection.removeNotificationListener(name,
699N/A listener,
699N/A sFilter,
699N/A sHandback,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.removeNotificationListener(name,
699N/A listener,
699N/A sFilter,
699N/A sHandback,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A }
0N/A
0N/A // Specific Notification Handle ----------------------------------
0N/A
0N/A public void addNotificationListener(ObjectName name,
699N/A NotificationListener listener,
699N/A NotificationFilter filter,
699N/A Object handback)
0N/A throws InstanceNotFoundException,
699N/A IOException {
0N/A
0N/A final boolean debug = logger.debugOn();
469N/A
0N/A if (debug)
0N/A logger.debug("addNotificationListener" +
699N/A "(ObjectName,NotificationListener,"+
699N/A "NotificationFilter,Object)",
699N/A "name=" + name
699N/A + ", listener=" + listener
699N/A + ", filter=" + filter
699N/A + ", handback=" + handback);
0N/A
0N/A final Integer listenerID =
699N/A addListenerWithSubject(name,
699N/A new MarshalledObject<NotificationFilter>(filter),
699N/A delegationSubject,true);
0N/A rmiNotifClient.addNotificationListener(listenerID, name, listener,
699N/A filter, handback,
699N/A delegationSubject);
0N/A }
0N/A
0N/A public void removeNotificationListener(ObjectName name,
699N/A NotificationListener listener)
0N/A throws InstanceNotFoundException,
469N/A ListenerNotFoundException,
469N/A IOException {
469N/A
0N/A final boolean debug = logger.debugOn();
0N/A
0N/A if (debug) logger.debug("removeNotificationListener"+
699N/A "(ObjectName,NotificationListener)",
699N/A "name=" + name
699N/A + ", listener=" + listener);
0N/A
0N/A final Integer[] ret =
699N/A rmiNotifClient.removeNotificationListener(name, listener);
0N/A
0N/A if (debug) logger.debug("removeNotificationListener",
699N/A "listenerIDs=" + objects(ret));
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A
0N/A try {
0N/A connection.removeNotificationListeners(name,
699N/A ret,
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.removeNotificationListeners(name,
699N/A ret,
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A
0N/A }
0N/A
0N/A public void removeNotificationListener(ObjectName name,
699N/A NotificationListener listener,
699N/A NotificationFilter filter,
699N/A Object handback)
699N/A throws InstanceNotFoundException,
699N/A ListenerNotFoundException,
699N/A IOException {
0N/A final boolean debug = logger.debugOn();
0N/A
0N/A if (debug)
0N/A logger.debug("removeNotificationListener"+
699N/A "(ObjectName,NotificationListener,"+
699N/A "NotificationFilter,Object)",
699N/A "name=" + name
699N/A + ", listener=" + listener
699N/A + ", filter=" + filter
699N/A + ", handback=" + handback);
0N/A
0N/A final Integer ret =
699N/A rmiNotifClient.removeNotificationListener(name, listener,
699N/A filter, handback);
0N/A
0N/A if (debug) logger.debug("removeNotificationListener",
699N/A "listenerID=" + ret);
0N/A
0N/A final ClassLoader old = pushDefaultClassLoader();
0N/A try {
0N/A connection.removeNotificationListeners(name,
699N/A new Integer[] {ret},
699N/A delegationSubject);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.removeNotificationListeners(name,
699N/A new Integer[] {ret},
699N/A delegationSubject);
0N/A } finally {
0N/A popDefaultClassLoader(old);
0N/A }
0N/A
0N/A }
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A private class RMINotifClient extends ClientNotifForwarder {
686N/A public RMINotifClient(ClassLoader cl, Map<String, ?> env) {
0N/A super(cl, env);
0N/A }
0N/A
0N/A protected NotificationResult fetchNotifs(long clientSequenceNumber,
699N/A int maxNotifications,
699N/A long timeout)
0N/A throws IOException, ClassNotFoundException {
0N/A IOException org;
0N/A
0N/A while (true) { // used for a successful re-connection
0N/A try {
0N/A return connection.fetchNotifications(clientSequenceNumber,
699N/A maxNotifications,
699N/A timeout);
0N/A } catch (IOException ioe) {
0N/A org = ioe;
0N/A
0N/A // inform of IOException
0N/A try {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A // The connection should be re-established.
0N/A continue;
0N/A } catch (IOException ee) {
0N/A // No more fetch, the Exception will be re-thrown.
0N/A break;
0N/A } // never reached
0N/A } // never reached
0N/A }
0N/A
0N/A // specially treating for an UnmarshalException
0N/A if (org instanceof UnmarshalException) {
0N/A UnmarshalException ume = (UnmarshalException)org;
0N/A
0N/A if (ume.detail instanceof ClassNotFoundException)
0N/A throw (ClassNotFoundException) ume.detail;
0N/A
0N/A /* In Sun's RMI implementation, if a method return
0N/A contains an unserializable object, then we get
0N/A UnmarshalException wrapping WriteAbortedException
0N/A wrapping NotSerializableException. In that case we
0N/A extract the NotSerializableException so that our
0N/A caller can realize it should try to skip past the
0N/A notification that presumably caused it. It's not
0N/A certain that every other RMI implementation will
0N/A generate this exact exception sequence. If not, we
0N/A will not detect that the problem is due to an
0N/A unserializable object, and we will stop trying to
0N/A receive notifications from the server. It's not
0N/A clear we can do much better. */
0N/A if (ume.detail instanceof WriteAbortedException) {
0N/A WriteAbortedException wae =
699N/A (WriteAbortedException) ume.detail;
0N/A if (wae.detail instanceof IOException)
0N/A throw (IOException) wae.detail;
0N/A }
0N/A } else if (org instanceof MarshalException) {
0N/A // IIOP will throw MarshalException wrapping a NotSerializableException
0N/A // when a server fails to serialize a response.
0N/A MarshalException me = (MarshalException)org;
0N/A if (me.detail instanceof NotSerializableException) {
0N/A throw (NotSerializableException)me.detail;
0N/A }
0N/A }
0N/A
0N/A // Not serialization problem, simply re-throw the orginal exception
0N/A throw org;
0N/A }
0N/A
0N/A protected Integer addListenerForMBeanRemovedNotif()
699N/A throws IOException, InstanceNotFoundException {
0N/A NotificationFilterSupport clientFilter =
699N/A new NotificationFilterSupport();
0N/A clientFilter.enableType(
699N/A MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
277N/A MarshalledObject<NotificationFilter> sFilter =
277N/A new MarshalledObject<NotificationFilter>(clientFilter);
0N/A
0N/A Integer[] listenerIDs;
0N/A final ObjectName[] names =
0N/A new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
686N/A final MarshalledObject<NotificationFilter>[] filters =
686N/A Util.cast(new MarshalledObject<?>[] {sFilter});
0N/A final Subject[] subjects = new Subject[] {null};
0N/A try {
0N/A listenerIDs =
699N/A connection.addNotificationListeners(names,
699N/A filters,
699N/A subjects);
0N/A
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A listenerIDs =
699N/A connection.addNotificationListeners(names,
699N/A filters,
699N/A subjects);
0N/A }
0N/A return listenerIDs[0];
0N/A }
0N/A
0N/A protected void removeListenerForMBeanRemovedNotif(Integer id)
699N/A throws IOException, InstanceNotFoundException,
699N/A ListenerNotFoundException {
0N/A try {
0N/A connection.removeNotificationListeners(
699N/A MBeanServerDelegate.DELEGATE_NAME,
699N/A new Integer[] {id},
699N/A null);
0N/A } catch (IOException ioe) {
0N/A communicatorAdmin.gotIOException(ioe);
0N/A
0N/A connection.removeNotificationListeners(
699N/A MBeanServerDelegate.DELEGATE_NAME,
699N/A new Integer[] {id},
699N/A null);
0N/A }
0N/A
0N/A }
0N/A
0N/A protected void lostNotifs(String message, long number) {
0N/A final String notifType = JMXConnectionNotification.NOTIFS_LOST;
0N/A
0N/A final JMXConnectionNotification n =
0N/A new JMXConnectionNotification(notifType,
0N/A RMIConnector.this,
0N/A connectionId,
0N/A clientNotifCounter++,
0N/A message,
277N/A Long.valueOf(number));
0N/A sendNotification(n);
0N/A }
0N/A }
0N/A
0N/A private class RMIClientCommunicatorAdmin extends ClientCommunicatorAdmin {
0N/A public RMIClientCommunicatorAdmin(long period) {
0N/A super(period);
0N/A }
0N/A
1790N/A @Override
670N/A public void gotIOException(IOException ioe) throws IOException {
0N/A if (ioe instanceof NoSuchObjectException) {
0N/A // need to restart
0N/A super.gotIOException(ioe);
0N/A
0N/A return;
0N/A }
0N/A
0N/A // check if the connection is broken
0N/A try {
0N/A connection.getDefaultDomain(null);
0N/A } catch (IOException ioexc) {
0N/A boolean toClose = false;
0N/A
0N/A synchronized(this) {
0N/A if (!terminated) {
0N/A terminated = true;
0N/A
0N/A toClose = true;
0N/A }
0N/A }
0N/A
0N/A if (toClose) {
0N/A // we should close the connection,
0N/A // but send a failed notif at first
0N/A final Notification failedNotif =
699N/A new JMXConnectionNotification(
0N/A JMXConnectionNotification.FAILED,
0N/A this,
0N/A connectionId,
0N/A clientNotifSeqNo++,
0N/A "Failed to communicate with the server: "+ioe.toString(),
0N/A ioe);
0N/A
0N/A sendNotification(failedNotif);
0N/A
0N/A try {
0N/A close(true);
0N/A } catch (Exception e) {
0N/A // OK.
0N/A // We are closing
0N/A }
0N/A }
0N/A }
0N/A
0N/A // forward the exception
0N/A if (ioe instanceof ServerException) {
0N/A /* Need to unwrap the exception.
0N/A Some user-thrown exception at server side will be wrapped by
0N/A rmi into a ServerException.
0N/A For example, a RMIConnnectorServer will wrap a
0N/A ClassNotFoundException into a UnmarshalException, and rmi
0N/A will throw a ServerException at client side which wraps this
0N/A UnmarshalException.
0N/A No failed notif here.
699N/A */
0N/A Throwable tt = ((ServerException)ioe).detail;
0N/A
0N/A if (tt instanceof IOException) {
0N/A throw (IOException)tt;
0N/A } else if (tt instanceof RuntimeException) {
0N/A throw (RuntimeException)tt;
0N/A }
0N/A }
0N/A
0N/A throw ioe;
0N/A }
0N/A
0N/A public void reconnectNotificationListeners(ClientListenerInfo[] old) throws IOException {
0N/A final int len = old.length;
0N/A int i;
0N/A
0N/A ClientListenerInfo[] clis = new ClientListenerInfo[len];
0N/A
0N/A final Subject[] subjects = new Subject[len];
0N/A final ObjectName[] names = new ObjectName[len];
0N/A final NotificationListener[] listeners = new NotificationListener[len];
0N/A final NotificationFilter[] filters = new NotificationFilter[len];
686N/A final MarshalledObject<NotificationFilter>[] mFilters =
686N/A Util.cast(new MarshalledObject<?>[len]);
0N/A final Object[] handbacks = new Object[len];
0N/A
0N/A for (i=0;i<len;i++) {
0N/A subjects[i] = old[i].getDelegationSubject();
0N/A names[i] = old[i].getObjectName();
0N/A listeners[i] = old[i].getListener();
0N/A filters[i] = old[i].getNotificationFilter();
0N/A mFilters[i] = new MarshalledObject<NotificationFilter>(filters[i]);
0N/A handbacks[i] = old[i].getHandback();
0N/A }
0N/A
0N/A try {
0N/A Integer[] ids = addListenersWithSubjects(names,mFilters,subjects,false);
0N/A
0N/A for (i=0;i<len;i++) {
0N/A clis[i] = new ClientListenerInfo(ids[i],
699N/A names[i],
699N/A listeners[i],
699N/A filters[i],
699N/A handbacks[i],
699N/A subjects[i]);
0N/A }
0N/A
0N/A rmiNotifClient.postReconnection(clis);
0N/A
0N/A return;
0N/A } catch (InstanceNotFoundException infe) {
0N/A // OK, we will do one by one
0N/A }
0N/A
0N/A int j = 0;
0N/A for (i=0;i<len;i++) {
0N/A try {
0N/A Integer id = addListenerWithSubject(names[i],
0N/A new MarshalledObject<NotificationFilter>(filters[i]),
0N/A subjects[i],
0N/A false);
0N/A
0N/A clis[j++] = new ClientListenerInfo(id,
699N/A names[i],
699N/A listeners[i],
699N/A filters[i],
699N/A handbacks[i],
699N/A subjects[i]);
0N/A } catch (InstanceNotFoundException infe) {
0N/A logger.warning("reconnectNotificationListeners",
699N/A "Can't reconnect listener for " +
699N/A names[i]);
0N/A }
0N/A }
0N/A
0N/A if (j != len) {
0N/A ClientListenerInfo[] tmp = clis;
0N/A clis = new ClientListenerInfo[j];
0N/A System.arraycopy(tmp, 0, clis, 0, j);
0N/A }
0N/A
0N/A rmiNotifClient.postReconnection(clis);
0N/A }
0N/A
0N/A protected void checkConnection() throws IOException {
0N/A if (logger.debugOn())
0N/A logger.debug("RMIClientCommunicatorAdmin-checkConnection",
699N/A "Calling the method getDefaultDomain.");
0N/A
0N/A connection.getDefaultDomain(null);
0N/A }
0N/A
0N/A protected void doStart() throws IOException {
0N/A // Get RMIServer stub from directory or URL encoding if needed.
277N/A RMIServer stub;
0N/A try {
0N/A stub = (rmiServer!=null)?rmiServer:
0N/A findRMIServer(jmxServiceURL, env);
0N/A } catch (NamingException ne) {
0N/A throw new IOException("Failed to get a RMI stub: "+ne);
0N/A }
0N/A
0N/A // Connect IIOP Stub if needed.
0N/A stub = connectStub(stub,env);
0N/A
0N/A // Calling newClient on the RMIServer stub.
0N/A Object credentials = env.get(CREDENTIALS);
0N/A connection = stub.newClient(credentials);
0N/A
0N/A // notif issues
0N/A final ClientListenerInfo[] old = rmiNotifClient.preReconnection();
0N/A
0N/A reconnectNotificationListeners(old);
0N/A
0N/A connectionId = getConnectionId();
0N/A
0N/A Notification reconnectedNotif =
699N/A new JMXConnectionNotification(JMXConnectionNotification.OPENED,
699N/A this,
699N/A connectionId,
699N/A clientNotifSeqNo++,
699N/A "Reconnected to server",
699N/A null);
0N/A sendNotification(reconnectedNotif);
0N/A
0N/A }
0N/A
0N/A protected void doStop() {
0N/A try {
0N/A close();
0N/A } catch (IOException ioe) {
0N/A logger.warning("RMIClientCommunicatorAdmin-doStop",
699N/A "Failed to call the method close():" + ioe);
0N/A logger.debug("RMIClientCommunicatorAdmin-doStop",ioe);
0N/A }
0N/A }
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A // Private stuff - Serialization
0N/A //--------------------------------------------------------------------
0N/A /**
0N/A * <p>In order to be usable, an IIOP stub must be connected to an ORB.
0N/A * The stub is automatically connected to the ORB if:
0N/A * <ul>
0N/A * <li> It was returned by the COS naming</li>
0N/A * <li> Its server counterpart has been registered in COS naming
0N/A * through JNDI.</li>
0N/A * </ul>
0N/A * Otherwise, it is not connected. A stub which is deserialized
0N/A * from Jini is not connected. A stub which is obtained from a
0N/A * non registered RMIIIOPServerImpl is not a connected.<br>
0N/A * A stub which is not connected can't be serialized, and thus
0N/A * can't be registered in Jini. A stub which is not connected can't
0N/A * be used to invoke methods on the server.
0N/A * <p>
0N/A * In order to palliate this, this method will connect the
0N/A * given stub if it is not yet connected. If the given
0N/A * <var>RMIServer</var> is not an instance of
0N/A * {@link javax.rmi.CORBA.Stub javax.rmi.CORBA.Stub}, then the
0N/A * method do nothing and simply returns that stub. Otherwise,
0N/A * this method will attempt to connect the stub to an ORB as
0N/A * follows:
0N/A * <ul>
0N/A * <p>This method looks in the provided <var>environment</var> for
0N/A * the "java.naming.corba.orb" property. If it is found, the
0N/A * referenced object (an {@link org.omg.CORBA.ORB ORB}) is used to
0N/A * connect the stub. Otherwise, a new org.omg.CORBA.ORB is created
0N/A * by calling {@link
0N/A * org.omg.CORBA.ORB#init(String[], Properties)
0N/A * org.omg.CORBA.ORB.init((String[])null,(Properties)null)}
0N/A * <p>The new created ORB is kept in a static
0N/A * {@link WeakReference} and can be reused for connecting other
0N/A * stubs. However, no reference is ever kept on the ORB provided
0N/A * in the <var>environment</var> map, if any.
0N/A * </ul>
0N/A * @param rmiServer A RMI Server Stub.
0N/A * @param environment An environment map, possibly containing an ORB.
0N/A * @return the given stub.
0N/A * @exception IllegalArgumentException if the
0N/A * <tt>java.naming.corba.orb</tt> property is specified and
0N/A * does not point to an {@link org.omg.CORBA.ORB ORB}.
0N/A * @exception IOException if the connection to the ORB failed.
0N/A **/
0N/A static RMIServer connectStub(RMIServer rmiServer,
686N/A Map<String, ?> environment)
0N/A throws IOException {
1801N/A if (IIOPHelper.isStub(rmiServer)) {
0N/A try {
1801N/A IIOPHelper.getOrb(rmiServer);
1801N/A } catch (UnsupportedOperationException x) {
1801N/A // BAD_OPERATION
1801N/A IIOPHelper.connect(rmiServer, resolveOrb(environment));
0N/A }
0N/A }
0N/A return rmiServer;
0N/A }
0N/A
0N/A /**
0N/A * Get the ORB specified by <var>environment</var>, or create a
0N/A * new one.
0N/A * <p>This method looks in the provided <var>environment</var> for
0N/A * the "java.naming.corba.orb" property. If it is found, the
0N/A * referenced object (an {@link org.omg.CORBA.ORB ORB}) is
0N/A * returned. Otherwise, a new org.omg.CORBA.ORB is created
0N/A * by calling {@link
0N/A * org.omg.CORBA.ORB#init(String[], java.util.Properties)
0N/A * org.omg.CORBA.ORB.init((String[])null,(Properties)null)}
0N/A * <p>The new created ORB is kept in a static
0N/A * {@link WeakReference} and can be reused for connecting other
0N/A * stubs. However, no reference is ever kept on the ORB provided
0N/A * in the <var>environment</var> map, if any.
0N/A * @param environment An environment map, possibly containing an ORB.
0N/A * @return An ORB.
0N/A * @exception IllegalArgumentException if the
0N/A * <tt>java.naming.corba.orb</tt> property is specified and
0N/A * does not point to an {@link org.omg.CORBA.ORB ORB}.
0N/A * @exception IOException if the ORB initialization failed.
0N/A **/
1801N/A static Object resolveOrb(Map<String, ?> environment)
0N/A throws IOException {
0N/A if (environment != null) {
0N/A final Object orb = environment.get(EnvHelp.DEFAULT_ORB);
1801N/A if (orb != null && !(IIOPHelper.isOrb(orb)))
0N/A throw new IllegalArgumentException(EnvHelp.DEFAULT_ORB +
699N/A " must be an instance of org.omg.CORBA.ORB.");
1801N/A if (orb != null) return orb;
0N/A }
1801N/A final Object orb =
699N/A (RMIConnector.orb==null)?null:RMIConnector.orb.get();
0N/A if (orb != null) return orb;
0N/A
1801N/A final Object newOrb =
1801N/A IIOPHelper.createOrb((String[])null, (Properties)null);
1801N/A RMIConnector.orb = new WeakReference<Object>(newOrb);
0N/A return newOrb;
0N/A }
0N/A
0N/A /**
0N/A * Read RMIConnector fields from an {@link java.io.ObjectInputStream
0N/A * ObjectInputStream}.
0N/A * Calls <code>s.defaultReadObject()</code> and then initializes
0N/A * all transient variables that need initializing.
0N/A * @param s The ObjectInputStream to read from.
0N/A * @exception InvalidObjectException if none of <var>rmiServer</var> stub
0N/A * or <var>jmxServiceURL</var> are set.
0N/A * @see #RMIConnector(JMXServiceURL,Map)
0N/A * @see #RMIConnector(RMIServer,Map)
0N/A **/
0N/A private void readObject(java.io.ObjectInputStream s)
699N/A throws IOException, ClassNotFoundException {
0N/A s.defaultReadObject();
0N/A
0N/A if (rmiServer == null && jmxServiceURL == null) throw new
699N/A InvalidObjectException("rmiServer and jmxServiceURL both null");
0N/A
0N/A initTransients();
0N/A }
0N/A
0N/A /**
0N/A * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream
0N/A * ObjectOutputStream}.
0N/A * <p>Connects the underlying RMIServer stub to an ORB, if needed,
0N/A * before serializing it. This is done using the environment
0N/A * map that was provided to the constructor, if any, and as documented
0N/A * in {@link javax.management.remote.rmi}.</p>
0N/A * <p>This method then calls <code>s.defaultWriteObject()</code>.
0N/A * Usually, <var>rmiServer</var> is null if this object
0N/A * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var>
0N/A * is null if this object is constructed with a RMIServer stub.
0N/A * <p>Note that the environment Map is not serialized, since the objects
0N/A * it contains are assumed to be contextual and relevant only
0N/A * with respect to the local environment (class loader, ORB, etc...).</p>
0N/A * <p>After an RMIConnector is deserialized, it is assumed that the
0N/A * user will call {@link #connect(Map)}, providing a new Map that
0N/A * can contain values which are contextually relevant to the new
0N/A * local environment.</p>
0N/A * <p>Since connection to the ORB is needed prior to serializing, and
0N/A * since the ORB to connect to is one of those contextual parameters,
0N/A * it is not recommended to re-serialize a just de-serialized object -
0N/A * as the de-serialized object has no map. Thus, when an RMIConnector
0N/A * object is needed for serialization or transmission to a remote
0N/A * application, it is recommended to obtain a new RMIConnector stub
0N/A * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p>
0N/A * @param s The ObjectOutputStream to write to.
0N/A * @exception InvalidObjectException if none of <var>rmiServer</var> stub
0N/A * or <var>jmxServiceURL</var> are set.
0N/A * @see #RMIConnector(JMXServiceURL,Map)
0N/A * @see #RMIConnector(RMIServer,Map)
0N/A **/
0N/A private void writeObject(java.io.ObjectOutputStream s)
699N/A throws IOException {
0N/A if (rmiServer == null && jmxServiceURL == null) throw new
699N/A InvalidObjectException("rmiServer and jmxServiceURL both null.");
0N/A connectStub(this.rmiServer,env);
0N/A s.defaultWriteObject();
0N/A }
0N/A
0N/A // Initialization of transient variables.
0N/A private void initTransients() {
0N/A rmbscMap = new WeakHashMap<Subject, MBeanServerConnection>();
0N/A connected = false;
0N/A terminated = false;
0N/A
0N/A connectionBroadcaster = new NotificationBroadcasterSupport();
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A // Private stuff - Check if stub can be trusted.
0N/A //--------------------------------------------------------------------
0N/A
0N/A private static void checkStub(Remote stub,
699N/A Class<?> stubClass) {
0N/A
0N/A // Check remote stub is from the expected class.
0N/A //
0N/A if (stub.getClass() != stubClass) {
0N/A if (!Proxy.isProxyClass(stub.getClass())) {
0N/A throw new SecurityException(
699N/A "Expecting a " + stubClass.getName() + " stub!");
0N/A } else {
0N/A InvocationHandler handler = Proxy.getInvocationHandler(stub);
0N/A if (handler.getClass() != RemoteObjectInvocationHandler.class)
0N/A throw new SecurityException(
699N/A "Expecting a dynamic proxy instance with a " +
699N/A RemoteObjectInvocationHandler.class.getName() +
699N/A " invocation handler!");
0N/A else
0N/A stub = (Remote) handler;
0N/A }
0N/A }
0N/A
0N/A // Check RemoteRef in stub is from the expected class
0N/A // "sun.rmi.server.UnicastRef2".
0N/A //
0N/A RemoteRef ref = ((RemoteObject)stub).getRef();
0N/A if (ref.getClass() != UnicastRef2.class)
0N/A throw new SecurityException(
699N/A "Expecting a " + UnicastRef2.class.getName() +
699N/A " remote reference in stub!");
0N/A
0N/A // Check RMIClientSocketFactory in stub is from the expected class
0N/A // "javax.rmi.ssl.SslRMIClientSocketFactory".
0N/A //
0N/A LiveRef liveRef = ((UnicastRef2)ref).getLiveRef();
0N/A RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
0N/A if (csf == null || csf.getClass() != SslRMIClientSocketFactory.class)
0N/A throw new SecurityException(
699N/A "Expecting a " + SslRMIClientSocketFactory.class.getName() +
699N/A " RMI client socket factory in stub!");
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A // Private stuff - RMIServer creation
0N/A //--------------------------------------------------------------------
0N/A
0N/A private RMIServer findRMIServer(JMXServiceURL directoryURL,
699N/A Map<String, Object> environment)
699N/A throws NamingException, IOException {
0N/A final boolean isIiop = RMIConnectorServer.isIiopURL(directoryURL,true);
0N/A if (isIiop) {
0N/A // Make sure java.naming.corba.orb is in the Map.
0N/A environment.put(EnvHelp.DEFAULT_ORB,resolveOrb(environment));
0N/A }
0N/A
0N/A String path = directoryURL.getURLPath();
0N/A int end = path.indexOf(';');
0N/A if (end < 0) end = path.length();
0N/A if (path.startsWith("/jndi/"))
0N/A return findRMIServerJNDI(path.substring(6,end), environment, isIiop);
0N/A else if (path.startsWith("/stub/"))
0N/A return findRMIServerJRMP(path.substring(6,end), environment, isIiop);
1801N/A else if (path.startsWith("/ior/")) {
1801N/A if (!IIOPHelper.isAvailable())
1801N/A throw new IOException("iiop protocol not available");
0N/A return findRMIServerIIOP(path.substring(5,end), environment, isIiop);
1801N/A } else {
0N/A final String msg = "URL path must begin with /jndi/ or /stub/ " +
699N/A "or /ior/: " + path;
0N/A throw new MalformedURLException(msg);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Lookup the RMIServer stub in a directory.
0N/A * @param jndiURL A JNDI URL indicating the location of the Stub
0N/A * (see {@link javax.management.remote.rmi}), e.g.:
0N/A * <ul><li><tt>rmi://registry-host:port/rmi-stub-name</tt></li>
0N/A * <li>or <tt>iiop://cosnaming-host:port/iiop-stub-name</tt></li>
0N/A * <li>or <tt>ldap://ldap-host:port/java-container-dn</tt></li>
0N/A * </ul>
0N/A * @param env the environment Map passed to the connector.
0N/A * @param isIiop true if the stub is expected to be an IIOP stub.
0N/A * @return The retrieved RMIServer stub.
0N/A * @exception NamingException if the stub couldn't be found.
0N/A **/
0N/A private RMIServer findRMIServerJNDI(String jndiURL, Map<String, ?> env,
699N/A boolean isIiop)
699N/A throws NamingException {
0N/A
0N/A InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env));
0N/A
0N/A Object objref = ctx.lookup(jndiURL);
0N/A ctx.close();
0N/A
0N/A if (isIiop)
0N/A return narrowIIOPServer(objref);
0N/A else
0N/A return narrowJRMPServer(objref);
0N/A }
0N/A
0N/A private static RMIServer narrowJRMPServer(Object objref) {
0N/A
0N/A return (RMIServer) objref;
0N/A }
0N/A
0N/A private static RMIServer narrowIIOPServer(Object objref) {
0N/A try {
1801N/A return IIOPHelper.narrow(objref, RMIServer.class);
0N/A } catch (ClassCastException e) {
0N/A if (logger.traceOn())
0N/A logger.trace("narrowIIOPServer","Failed to narrow objref=" +
699N/A objref + ": " + e);
0N/A if (logger.debugOn()) logger.debug("narrowIIOPServer",e);
0N/A return null;
0N/A }
0N/A }
0N/A
686N/A private RMIServer findRMIServerIIOP(String ior, Map<String, ?> env, boolean isIiop) {
0N/A // could forbid "rmi:" URL here -- but do we need to?
1801N/A final Object orb = env.get(EnvHelp.DEFAULT_ORB);
1801N/A final Object stub = IIOPHelper.stringToObject(orb, ior);
1801N/A return IIOPHelper.narrow(stub, RMIServer.class);
0N/A }
0N/A
686N/A private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env, boolean isIiop)
0N/A throws IOException {
0N/A // could forbid "iiop:" URL here -- but do we need to?
0N/A final byte[] serialized;
0N/A try {
0N/A serialized = base64ToByteArray(base64);
0N/A } catch (IllegalArgumentException e) {
0N/A throw new MalformedURLException("Bad BASE64 encoding: " +
699N/A e.getMessage());
0N/A }
0N/A final ByteArrayInputStream bin = new ByteArrayInputStream(serialized);
0N/A
0N/A final ClassLoader loader = EnvHelp.resolveClientClassLoader(env);
0N/A final ObjectInputStream oin =
699N/A (loader == null) ?
699N/A new ObjectInputStream(bin) :
699N/A new ObjectInputStreamWithLoader(bin, loader);
0N/A final Object stub;
0N/A try {
0N/A stub = oin.readObject();
0N/A } catch (ClassNotFoundException e) {
0N/A throw new MalformedURLException("Class not found: " + e);
0N/A }
1801N/A return (RMIServer)stub;
0N/A }
0N/A
0N/A private static final class ObjectInputStreamWithLoader
0N/A extends ObjectInputStream {
0N/A ObjectInputStreamWithLoader(InputStream in, ClassLoader cl)
699N/A throws IOException {
0N/A super(in);
0N/A this.loader = cl;
0N/A }
0N/A
686N/A @Override
686N/A protected Class<?> resolveClass(ObjectStreamClass classDesc)
0N/A throws IOException, ClassNotFoundException {
6298N/A String name = classDesc.getName();
6298N/A ReflectUtil.checkPackageAccess(name);
6298N/A return Class.forName(name, false, loader);
0N/A }
0N/A
0N/A private final ClassLoader loader;
0N/A }
0N/A
0N/A /*
0N/A The following section of code avoids a class loading problem
0N/A with RMI. The problem is that an RMI stub, when deserializing
0N/A a remote method return value or exception, will first of all
0N/A consult the first non-bootstrap class loader it finds in the
0N/A call stack. This can lead to behavior that is not portable
0N/A between implementations of the JMX Remote API. Notably, an
0N/A implementation on J2SE 1.4 will find the RMI stub's loader on
0N/A the stack. But in J2SE 5, this stub is loaded by the
0N/A bootstrap loader, so RMI will find the loader of the user code
0N/A that called an MBeanServerConnection method.
0N/A
0N/A To avoid this problem, we take advantage of what the RMI stub
0N/A is doing internally. Each remote call will end up calling
0N/A ref.invoke(...), where ref is the RemoteRef parameter given to
0N/A the RMI stub's constructor. It is within this call that the
0N/A deserialization will happen. So we fabricate our own RemoteRef
0N/A that delegates everything to the "real" one but that is loaded
0N/A by a class loader that knows no other classes. The class
0N/A loader NoCallStackClassLoader does this: the RemoteRef is an
0N/A instance of the class named by proxyRefClassName, which is
0N/A fabricated by the class loader using byte code that is defined
0N/A by the string below.
0N/A
0N/A The call stack when the deserialization happens is thus this:
0N/A MBeanServerConnection.getAttribute (or whatever)
0N/A -> RMIConnectionImpl_Stub.getAttribute
0N/A -> ProxyRef.invoke(...getAttribute...)
0N/A -> UnicastRef.invoke(...getAttribute...)
0N/A -> internal RMI stuff
0N/A
0N/A Here UnicastRef is the RemoteRef created when the stub was
0N/A deserialized (which is of some RMI internal class). It and the
0N/A "internal RMI stuff" are loaded by the bootstrap loader, so are
0N/A transparent to the stack search. The first non-bootstrap
0N/A loader found is our ProxyRefLoader, as required.
0N/A
0N/A In a future version of this code as integrated into J2SE 5,
0N/A this workaround could be replaced by direct access to the
0N/A internals of RMI. For now, we use the same code base for J2SE
0N/A and for the standalone Reference Implementation.
0N/A
0N/A The byte code below encodes the following class, compiled using
0N/A J2SE 1.4.2 with the -g:none option.
0N/A
0N/A package com.sun.jmx.remote.internal;
0N/A
0N/A import java.lang.reflect.Method;
0N/A import java.rmi.Remote;
0N/A import java.rmi.server.RemoteRef;
0N/A import com.sun.jmx.remote.internal.ProxyRef;
0N/A
0N/A public class PRef extends ProxyRef {
0N/A public PRef(RemoteRef ref) {
0N/A super(ref);
0N/A }
0N/A
0N/A public Object invoke(Remote obj, Method method,
0N/A Object[] params, long opnum)
0N/A throws Exception {
0N/A return ref.invoke(obj, method, params, opnum);
0N/A }
0N/A }
0N/A */
0N/A
0N/A private static final String rmiServerImplStubClassName =
0N/A RMIServer.class.getName() + "Impl_Stub";
686N/A private static final Class<?> rmiServerImplStubClass;
0N/A private static final String rmiConnectionImplStubClassName =
699N/A RMIConnection.class.getName() + "Impl_Stub";
0N/A private static final Class<?> rmiConnectionImplStubClass;
0N/A private static final String pRefClassName =
0N/A "com.sun.jmx.remote.internal.PRef";
686N/A private static final Constructor<?> proxyRefConstructor;
0N/A static {
0N/A final String pRefByteCodeString =
699N/A "\312\376\272\276\0\0\0.\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17\0"+
699N/A "\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/RemoteRef;"+
699N/A ")V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/reflec"+
699N/A "t/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12Exception"+
699N/A "s\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1\0\40com/"+
699N/A "sun/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/internal/Pr"+
699N/A "oxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rmi/serve"+
699N/A "r/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5\0\0\0\0"+
699N/A "\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0\6*+\267\0\1\261"+
699N/A "\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0\6\0\0\0\17*\264\0"+
699N/A "\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0\4\0\1\0\14\0\0";
0N/A final byte[] pRefByteCode =
699N/A NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
0N/A PrivilegedExceptionAction<Constructor<?>> action =
0N/A new PrivilegedExceptionAction<Constructor<?>>() {
0N/A public Constructor<?> run() throws Exception {
0N/A Class thisClass = RMIConnector.class;
0N/A ClassLoader thisLoader = thisClass.getClassLoader();
0N/A ProtectionDomain thisProtectionDomain =
699N/A thisClass.getProtectionDomain();
0N/A String[] otherClassNames = {ProxyRef.class.getName()};
0N/A ClassLoader cl =
699N/A new NoCallStackClassLoader(pRefClassName,
699N/A pRefByteCode,
699N/A otherClassNames,
699N/A thisLoader,
699N/A thisProtectionDomain);
0N/A Class<?> c = cl.loadClass(pRefClassName);
0N/A return c.getConstructor(RemoteRef.class);
0N/A }
0N/A };
0N/A
686N/A Class<?> serverStubClass;
0N/A try {
0N/A serverStubClass = Class.forName(rmiServerImplStubClassName);
0N/A } catch (Exception e) {
0N/A logger.error("<clinit>",
699N/A "Failed to instantiate " +
699N/A rmiServerImplStubClassName + ": " + e);
0N/A logger.debug("<clinit>",e);
0N/A serverStubClass = null;
0N/A }
0N/A rmiServerImplStubClass = serverStubClass;
0N/A
0N/A Class<?> stubClass;
686N/A Constructor<?> constr;
0N/A try {
0N/A stubClass = Class.forName(rmiConnectionImplStubClassName);
686N/A constr = (Constructor<?>) AccessController.doPrivileged(action);
0N/A } catch (Exception e) {
0N/A logger.error("<clinit>",
699N/A "Failed to initialize proxy reference constructor "+
699N/A "for " + rmiConnectionImplStubClassName + ": " + e);
0N/A logger.debug("<clinit>",e);
0N/A stubClass = null;
0N/A constr = null;
0N/A }
0N/A rmiConnectionImplStubClass = stubClass;
0N/A proxyRefConstructor = constr;
0N/A }
0N/A
0N/A private static RMIConnection shadowJrmpStub(RemoteObject stub)
699N/A throws InstantiationException, IllegalAccessException,
699N/A InvocationTargetException, ClassNotFoundException,
699N/A NoSuchMethodException {
0N/A RemoteRef ref = stub.getRef();
0N/A RemoteRef proxyRef = (RemoteRef)
0N/A proxyRefConstructor.newInstance(new Object[] {ref});
686N/A final Constructor<?> rmiConnectionImplStubConstructor =
686N/A rmiConnectionImplStubClass.getConstructor(RemoteRef.class);
0N/A Object[] args = {proxyRef};
0N/A RMIConnection proxyStub = (RMIConnection)
699N/A rmiConnectionImplStubConstructor.newInstance(args);
0N/A return proxyStub;
0N/A }
0N/A
0N/A /*
0N/A The following code performs a similar trick for RMI/IIOP to the
0N/A one described above for RMI/JRMP. Unlike JRMP, though, we
0N/A can't easily insert an object between the RMIConnection stub
0N/A and the RMI/IIOP deserialization code, as explained below.
0N/A
0N/A A method in an RMI/IIOP stub does the following. It makes an
0N/A org.omg.CORBA_2_3.portable.OutputStream for each request, and
0N/A writes the parameters to it. Then it calls
0N/A _invoke(OutputStream) which it inherits from CORBA's
0N/A ObjectImpl. That returns an
0N/A org.omg.CORBA_2_3.portable.InputStream. The return value is
0N/A read from this InputStream. So the stack during
0N/A deserialization looks like this:
0N/A
0N/A MBeanServerConnection.getAttribute (or whatever)
0N/A -> _RMIConnection_Stub.getAttribute
0N/A -> Util.readAny (a CORBA method)
0N/A -> InputStream.read_any
0N/A -> internal CORBA stuff
0N/A
0N/A What we would have *liked* to have done would be the same thing
0N/A as for RMI/JRMP. We create a "ProxyDelegate" that is an
0N/A org.omg.CORBA.portable.Delegate that simply forwards every
0N/A operation to the real original Delegate from the RMIConnection
0N/A stub, except that the InputStream returned by _invoke is
0N/A wrapped by a "ProxyInputStream" that is loaded by our
0N/A NoCallStackClassLoader.
0N/A
0N/A Unfortunately, this doesn't work, at least with Sun's J2SE
0N/A 1.4.2, because the CORBA code is not designed to allow you to
0N/A change Delegates arbitrarily. You get a ClassCastException
0N/A from code that expects the Delegate to implement an internal
0N/A interface.
0N/A
0N/A So instead we do the following. We create a subclass of the
0N/A stub that overrides the _invoke method so as to wrap the
0N/A returned InputStream in a ProxyInputStream. We create a
0N/A subclass of ProxyInputStream using the NoCallStackClassLoader
0N/A and override its read_any and read_value(Class) methods.
0N/A (These are the only methods called during deserialization of
0N/A MBeanServerConnection return values.) We extract the Delegate
0N/A from the original stub and insert it into our subclass stub,
0N/A and away we go. The state of a stub consists solely of its
0N/A Delegate.
0N/A
0N/A We also need to catch ApplicationException, which will encode
0N/A any exceptions declared in the throws clause of the called
0N/A method. Its InputStream needs to be wrapped in a
0N/A ProxyInputSteam too.
0N/A
0N/A We override _releaseReply in the stub subclass so that it
0N/A replaces a ProxyInputStream argument with the original
0N/A InputStream. This avoids problems if the implementation of
0N/A _releaseReply ends up casting this InputStream to an
0N/A implementation-specific interface (which in Sun's J2SE 5 it
0N/A does).
0N/A
0N/A It is not strictly necessary for the stub subclass to be loaded
0N/A by a NoCallStackClassLoader, since the call-stack search stops
0N/A at the ProxyInputStream subclass. However, it is convenient
0N/A for two reasons. One is that it means that the
0N/A ProxyInputStream subclass can be accessed directly, without
0N/A using reflection. The other is that it avoids build problems,
0N/A since usually stubs are created after other classes are
0N/A compiled, so we can't access them from this class without,
0N/A again, using reflection.
0N/A
0N/A The strings below encode the following two Java classes,
1801N/A compiled using javac -g:none.
0N/A
1801N/A package com.sun.jmx.remote.protocol.iiop;
0N/A
0N/A import org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub;
0N/A
0N/A import org.omg.CORBA.portable.ApplicationException;
0N/A import org.omg.CORBA.portable.InputStream;
0N/A import org.omg.CORBA.portable.OutputStream;
0N/A import org.omg.CORBA.portable.RemarshalException;
0N/A
0N/A public class ProxyStub extends _RMIConnection_Stub {
0N/A public InputStream _invoke(OutputStream out)
0N/A throws ApplicationException, RemarshalException {
0N/A try {
0N/A return new PInputStream(super._invoke(out));
0N/A } catch (ApplicationException e) {
0N/A InputStream pis = new PInputStream(e.getInputStream());
0N/A throw new ApplicationException(e.getId(), pis);
0N/A }
0N/A }
0N/A
0N/A public void _releaseReply(InputStream in) {
1801N/A if (in != null)
1801N/A in = ((PInputStream)in).getProxiedInputStream();
1801N/A super._releaseReply(in);
0N/A }
0N/A }
0N/A
1801N/A package com.sun.jmx.remote.protocol.iiop;
0N/A
0N/A public class PInputStream extends ProxyInputStream {
0N/A public PInputStream(org.omg.CORBA.portable.InputStream in) {
0N/A super(in);
0N/A }
0N/A
0N/A public org.omg.CORBA.Any read_any() {
0N/A return in.read_any();
0N/A }
0N/A
0N/A public java.io.Serializable read_value(Class clz) {
0N/A return narrow().read_value(clz);
0N/A }
0N/A }
0N/A
0N/A
0N/A */
0N/A private static final String iiopConnectionStubClassName =
1801N/A "org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub";
0N/A private static final String proxyStubClassName =
1801N/A "com.sun.jmx.remote.protocol.iiop.ProxyStub";
1801N/A private static final String ProxyInputStreamClassName =
1801N/A "com.sun.jmx.remote.protocol.iiop.ProxyInputStream";
0N/A private static final String pInputStreamClassName =
1801N/A "com.sun.jmx.remote.protocol.iiop.PInputStream";
686N/A private static final Class<?> proxyStubClass;
0N/A static {
0N/A final String proxyStubByteCodeString =
1801N/A "\312\376\272\276\0\0\0\63\0+\12\0\14\0\30\7\0\31\12\0\14\0\32\12"+
1801N/A "\0\2\0\33\7\0\34\12\0\5\0\35\12\0\5\0\36\12\0\5\0\37\12\0\2\0 "+
1801N/A "\12\0\14\0!\7\0\"\7\0#\1\0\6<init>\1\0\3()V\1\0\4Code\1\0\7_in"+
1801N/A "voke\1\0K(Lorg/omg/CORBA/portable/OutputStream;)Lorg/omg/CORBA"+
1801N/A "/portable/InputStream;\1\0\15StackMapTable\7\0\34\1\0\12Except"+
1801N/A "ions\7\0$\1\0\15_releaseReply\1\0'(Lorg/omg/CORBA/portable/Inp"+
1801N/A "utStream;)V\14\0\15\0\16\1\0-com/sun/jmx/remote/protocol/iiop/"+
1801N/A "PInputStream\14\0\20\0\21\14\0\15\0\27\1\0+org/omg/CORBA/porta"+
1801N/A "ble/ApplicationException\14\0%\0&\14\0'\0(\14\0\15\0)\14\0*\0&"+
1801N/A "\14\0\26\0\27\1\0*com/sun/jmx/remote/protocol/iiop/ProxyStub\1"+
1801N/A "\0<org/omg/stub/javax/management/remote/rmi/_RMIConnection_Stu"+
1801N/A "b\1\0)org/omg/CORBA/portable/RemarshalException\1\0\16getInput"+
1801N/A "Stream\1\0&()Lorg/omg/CORBA/portable/InputStream;\1\0\5getId\1"+
1801N/A "\0\24()Ljava/lang/String;\1\09(Ljava/lang/String;Lorg/omg/CORB"+
1801N/A "A/portable/InputStream;)V\1\0\25getProxiedInputStream\0!\0\13\0"+
1801N/A "\14\0\0\0\0\0\3\0\1\0\15\0\16\0\1\0\17\0\0\0\21\0\1\0\1\0\0\0\5"+
1801N/A "*\267\0\1\261\0\0\0\0\0\1\0\20\0\21\0\2\0\17\0\0\0G\0\4\0\4\0\0"+
1801N/A "\0'\273\0\2Y*+\267\0\3\267\0\4\260M\273\0\2Y,\266\0\6\267\0\4N"+
1801N/A "\273\0\5Y,\266\0\7-\267\0\10\277\0\1\0\0\0\14\0\15\0\5\0\1\0\22"+
1801N/A "\0\0\0\6\0\1M\7\0\23\0\24\0\0\0\6\0\2\0\5\0\25\0\1\0\26\0\27\0"+
1801N/A "\1\0\17\0\0\0'\0\2\0\2\0\0\0\22+\306\0\13+\300\0\2\266\0\11L*+"+
1801N/A "\267\0\12\261\0\0\0\1\0\22\0\0\0\3\0\1\14\0\0";
0N/A final String pInputStreamByteCodeString =
1801N/A "\312\376\272\276\0\0\0\63\0\36\12\0\7\0\17\11\0\6\0\20\12\0\21"+
1801N/A "\0\22\12\0\6\0\23\12\0\24\0\25\7\0\26\7\0\27\1\0\6<init>\1\0'("+
1801N/A "Lorg/omg/CORBA/portable/InputStream;)V\1\0\4Code\1\0\10read_an"+
1801N/A "y\1\0\25()Lorg/omg/CORBA/Any;\1\0\12read_value\1\0)(Ljava/lang"+
1801N/A "/Class;)Ljava/io/Serializable;\14\0\10\0\11\14\0\30\0\31\7\0\32"+
1801N/A "\14\0\13\0\14\14\0\33\0\34\7\0\35\14\0\15\0\16\1\0-com/sun/jmx"+
1801N/A "/remote/protocol/iiop/PInputStream\1\0\61com/sun/jmx/remote/pr"+
1801N/A "otocol/iiop/ProxyInputStream\1\0\2in\1\0$Lorg/omg/CORBA/portab"+
1801N/A "le/InputStream;\1\0\"org/omg/CORBA/portable/InputStream\1\0\6n"+
1801N/A "arrow\1\0*()Lorg/omg/CORBA_2_3/portable/InputStream;\1\0&org/o"+
1801N/A "mg/CORBA_2_3/portable/InputStream\0!\0\6\0\7\0\0\0\0\0\3\0\1\0"+
1801N/A "\10\0\11\0\1\0\12\0\0\0\22\0\2\0\2\0\0\0\6*+\267\0\1\261\0\0\0"+
1801N/A "\0\0\1\0\13\0\14\0\1\0\12\0\0\0\24\0\1\0\1\0\0\0\10*\264\0\2\266"+
699N/A "\0\3\260\0\0\0\0\0\1\0\15\0\16\0\1\0\12\0\0\0\25\0\2\0\2\0\0\0"+
699N/A "\11*\266\0\4+\266\0\5\260\0\0\0\0\0\0";
0N/A final byte[] proxyStubByteCode =
699N/A NoCallStackClassLoader.stringToBytes(proxyStubByteCodeString);
0N/A final byte[] pInputStreamByteCode =
699N/A NoCallStackClassLoader.stringToBytes(pInputStreamByteCodeString);
0N/A final String[] classNames={proxyStubClassName, pInputStreamClassName};
0N/A final byte[][] byteCodes = {proxyStubByteCode, pInputStreamByteCode};
0N/A final String[] otherClassNames = {
0N/A iiopConnectionStubClassName,
1801N/A ProxyInputStreamClassName,
0N/A };
1801N/A if (IIOPHelper.isAvailable()) {
1801N/A PrivilegedExceptionAction<Class<?>> action =
0N/A new PrivilegedExceptionAction<Class<?>>() {
1801N/A public Class<?> run() throws Exception {
0N/A Class thisClass = RMIConnector.class;
0N/A ClassLoader thisLoader = thisClass.getClassLoader();
0N/A ProtectionDomain thisProtectionDomain =
699N/A thisClass.getProtectionDomain();
0N/A ClassLoader cl =
699N/A new NoCallStackClassLoader(classNames,
699N/A byteCodes,
699N/A otherClassNames,
699N/A thisLoader,
699N/A thisProtectionDomain);
0N/A return cl.loadClass(proxyStubClassName);
1801N/A }
1801N/A };
1801N/A Class<?> stubClass;
1801N/A try {
1801N/A stubClass = AccessController.doPrivileged(action);
1801N/A } catch (Exception e) {
1801N/A logger.error("<clinit>",
1801N/A "Unexpected exception making shadow IIOP stub class: "+e);
1801N/A logger.debug("<clinit>",e);
1801N/A stubClass = null;
0N/A }
1801N/A proxyStubClass = stubClass;
1801N/A } else {
1801N/A proxyStubClass = null;
0N/A }
0N/A }
0N/A
1801N/A private static RMIConnection shadowIiopStub(Object stub)
699N/A throws InstantiationException, IllegalAccessException {
1801N/A Object proxyStub = proxyStubClass.newInstance();
1801N/A IIOPHelper.setDelegate(proxyStub, IIOPHelper.getDelegate(stub));
0N/A return (RMIConnection) proxyStub;
0N/A }
0N/A
0N/A private static RMIConnection getConnection(RMIServer server,
699N/A Object credentials,
699N/A boolean checkStub)
0N/A throws IOException {
0N/A RMIConnection c = server.newClient(credentials);
0N/A if (checkStub) checkStub(c, rmiConnectionImplStubClass);
0N/A try {
0N/A if (c.getClass() == rmiConnectionImplStubClass)
0N/A return shadowJrmpStub((RemoteObject) c);
0N/A if (c.getClass().getName().equals(iiopConnectionStubClassName))
1801N/A return shadowIiopStub(c);
0N/A logger.trace("getConnection",
699N/A "Did not wrap " + c.getClass() + " to foil " +
699N/A "stack search for classes: class loading semantics " +
699N/A "may be incorrect");
0N/A } catch (Exception e) {
0N/A logger.error("getConnection",
699N/A "Could not wrap " + c.getClass() + " to foil " +
699N/A "stack search for classes: class loading semantics " +
699N/A "may be incorrect: " + e);
0N/A logger.debug("getConnection",e);
0N/A // so just return the original stub, which will work for all
0N/A // but the most exotic class loading situations
0N/A }
0N/A return c;
0N/A }
0N/A
0N/A private static byte[] base64ToByteArray(String s) {
0N/A int sLen = s.length();
0N/A int numGroups = sLen/4;
0N/A if (4*numGroups != sLen)
0N/A throw new IllegalArgumentException(
699N/A "String length must be a multiple of four.");
0N/A int missingBytesInLastGroup = 0;
0N/A int numFullGroups = numGroups;
0N/A if (sLen != 0) {
0N/A if (s.charAt(sLen-1) == '=') {
0N/A missingBytesInLastGroup++;
0N/A numFullGroups--;
0N/A }
0N/A if (s.charAt(sLen-2) == '=')
0N/A missingBytesInLastGroup++;
0N/A }
0N/A byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
0N/A
0N/A // Translate all full groups from base64 to byte array elements
0N/A int inCursor = 0, outCursor = 0;
0N/A for (int i=0; i<numFullGroups; i++) {
0N/A int ch0 = base64toInt(s.charAt(inCursor++));
0N/A int ch1 = base64toInt(s.charAt(inCursor++));
0N/A int ch2 = base64toInt(s.charAt(inCursor++));
0N/A int ch3 = base64toInt(s.charAt(inCursor++));
0N/A result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
0N/A result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
0N/A result[outCursor++] = (byte) ((ch2 << 6) | ch3);
0N/A }
0N/A
0N/A // Translate partial group, if present
0N/A if (missingBytesInLastGroup != 0) {
0N/A int ch0 = base64toInt(s.charAt(inCursor++));
0N/A int ch1 = base64toInt(s.charAt(inCursor++));
0N/A result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
0N/A
0N/A if (missingBytesInLastGroup == 1) {
0N/A int ch2 = base64toInt(s.charAt(inCursor++));
0N/A result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
0N/A }
0N/A }
0N/A // assert inCursor == s.length()-missingBytesInLastGroup;
0N/A // assert outCursor == result.length;
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * Translates the specified character, which is assumed to be in the
0N/A * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
0N/A *
0N/A * @throws IllegalArgumentException if
0N/A * c is not in the Base64 Alphabet.
0N/A */
0N/A private static int base64toInt(char c) {
0N/A int result;
0N/A
0N/A if (c >= base64ToInt.length)
0N/A result = -1;
0N/A else
0N/A result = base64ToInt[c];
0N/A
0N/A if (result < 0)
0N/A throw new IllegalArgumentException("Illegal character " + c);
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * This array is a lookup table that translates unicode characters
0N/A * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
0N/A * into their 6-bit positive integer equivalents. Characters that
0N/A * are not in the Base64 alphabet but fall within the bounds of the
0N/A * array are translated to -1.
0N/A */
0N/A private static final byte base64ToInt[] = {
0N/A -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0N/A -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0N/A -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
0N/A 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
0N/A 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
0N/A 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
0N/A 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
0N/A };
0N/A
0N/A //--------------------------------------------------------------------
0N/A // Private stuff - Find / Set default class loader
0N/A //--------------------------------------------------------------------
0N/A private ClassLoader pushDefaultClassLoader() {
0N/A final Thread t = Thread.currentThread();
0N/A final ClassLoader old = t.getContextClassLoader();
0N/A if (defaultClassLoader != null)
0N/A AccessController.doPrivileged(new PrivilegedAction<Void>() {
699N/A public Void run() {
699N/A t.setContextClassLoader(defaultClassLoader);
699N/A return null;
699N/A }
699N/A });
699N/A return old;
0N/A }
0N/A
0N/A private void popDefaultClassLoader(final ClassLoader old) {
0N/A AccessController.doPrivileged(new PrivilegedAction<Void>() {
699N/A public Void run() {
699N/A Thread.currentThread().setContextClassLoader(old);
699N/A return null;
699N/A }
699N/A });
0N/A }
0N/A
0N/A //--------------------------------------------------------------------
0N/A // Private variables
0N/A //--------------------------------------------------------------------
0N/A /**
0N/A * @serial The RMIServer stub of the RMI JMX Connector server to
0N/A * which this client connector is (or will be) connected. This
0N/A * field can be null when <var>jmxServiceURL</var> is not
0N/A * null. This includes the case where <var>jmxServiceURL</var>
0N/A * contains a serialized RMIServer stub. If both
0N/A * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
0N/A * serialization will fail.
0N/A *
0N/A * @see #RMIConnector(RMIServer,Map)
0N/A **/
0N/A private final RMIServer rmiServer;
0N/A
0N/A /**
0N/A * @serial The JMXServiceURL of the RMI JMX Connector server to
0N/A * which this client connector will be connected. This field can
0N/A * be null when <var>rmiServer</var> is not null. If both
0N/A * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
0N/A * serialization will fail.
0N/A *
0N/A * @see #RMIConnector(JMXServiceURL,Map)
0N/A **/
0N/A private final JMXServiceURL jmxServiceURL;
0N/A
0N/A // ---------------------------------------------------------
0N/A // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
0N/A // ---------------------------------------------------------
0N/A // Any transient variable which needs to be initialized should
0N/A // be initialized in the method initTransient()
0N/A private transient Map<String, Object> env;
0N/A private transient ClassLoader defaultClassLoader;
0N/A private transient RMIConnection connection;
0N/A private transient String connectionId;
0N/A
0N/A private transient long clientNotifSeqNo = 0;
0N/A
0N/A private transient WeakHashMap<Subject, MBeanServerConnection> rmbscMap;
0N/A
0N/A private transient RMINotifClient rmiNotifClient;
0N/A // = new RMINotifClient(new Integer(0));
0N/A
0N/A private transient long clientNotifCounter = 0;
0N/A
0N/A private transient boolean connected;
0N/A // = false;
0N/A private transient boolean terminated;
0N/A // = false;
0N/A
0N/A private transient Exception closeException;
0N/A
0N/A private transient NotificationBroadcasterSupport connectionBroadcaster;
0N/A
0N/A private transient ClientCommunicatorAdmin communicatorAdmin;
0N/A
0N/A /**
0N/A * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
0N/A * connect unconnected stubs.
0N/A **/
1801N/A private static volatile WeakReference<Object> orb = null;
0N/A
0N/A // TRACES & DEBUG
0N/A //---------------
0N/A private static String objects(final Object[] objs) {
0N/A if (objs == null)
0N/A return "null";
0N/A else
0N/A return Arrays.asList(objs).toString();
0N/A }
0N/A
0N/A private static String strings(final String[] strs) {
0N/A return objects(strs);
0N/A }
0N/A}