Source Code Cross Referenced for RMIConnector.java in  » 6.0-JDK-Core » management » javax » management » remote » rmi » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » management » javax.management.remote.rmi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.management.remote.rmi;
0027
0028        import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
0029        import com.sun.jmx.remote.internal.ClientListenerInfo;
0030        import com.sun.jmx.remote.internal.ClientNotifForwarder;
0031        import com.sun.jmx.remote.internal.ProxyInputStream;
0032        import com.sun.jmx.remote.internal.ProxyRef;
0033        import com.sun.jmx.remote.util.ClassLogger;
0034        import com.sun.jmx.remote.util.EnvHelp;
0035        import java.io.ByteArrayInputStream;
0036        import java.io.IOException;
0037        import java.io.InputStream;
0038        import java.io.InvalidObjectException;
0039        import java.io.NotSerializableException;
0040        import java.io.ObjectInputStream;
0041        import java.io.ObjectStreamClass;
0042        import java.io.Serializable;
0043        import java.io.WriteAbortedException;
0044        import java.lang.ref.WeakReference;
0045        import java.lang.reflect.Constructor;
0046        import java.lang.reflect.InvocationHandler;
0047        import java.lang.reflect.InvocationTargetException;
0048        import java.lang.reflect.Proxy;
0049        import java.net.MalformedURLException;
0050        import java.rmi.MarshalException;
0051        import java.rmi.MarshalledObject;
0052        import java.rmi.NoSuchObjectException;
0053        import java.rmi.Remote;
0054        import java.rmi.ServerException;
0055        import java.rmi.UnmarshalException;
0056        import java.rmi.server.RMIClientSocketFactory;
0057        import java.rmi.server.RemoteObject;
0058        import java.rmi.server.RemoteObjectInvocationHandler;
0059        import java.rmi.server.RemoteRef;
0060        import java.security.AccessController;
0061        import java.security.PrivilegedAction;
0062        import java.security.PrivilegedExceptionAction;
0063        import java.security.ProtectionDomain;
0064        import java.util.Arrays;
0065        import java.util.Collections;
0066        import java.util.HashMap;
0067        import java.util.Map;
0068        import java.util.Properties;
0069        import java.util.Set;
0070        import java.util.WeakHashMap;
0071        import javax.management.Attribute;
0072        import javax.management.AttributeList;
0073        import javax.management.AttributeNotFoundException;
0074        import javax.management.InstanceAlreadyExistsException;
0075        import javax.management.InstanceNotFoundException;
0076        import javax.management.IntrospectionException;
0077        import javax.management.InvalidAttributeValueException;
0078        import javax.management.ListenerNotFoundException;
0079        import javax.management.MBeanException;
0080        import javax.management.MBeanInfo;
0081        import javax.management.MBeanRegistrationException;
0082        import javax.management.MBeanServerConnection;
0083        import javax.management.MBeanServerDelegate;
0084        import javax.management.MBeanServerNotification;
0085        import javax.management.NotCompliantMBeanException;
0086        import javax.management.Notification;
0087        import javax.management.NotificationBroadcasterSupport;
0088        import javax.management.NotificationFilter;
0089        import javax.management.NotificationFilterSupport;
0090        import javax.management.NotificationListener;
0091        import javax.management.ObjectInstance;
0092        import javax.management.ObjectName;
0093        import javax.management.QueryExp;
0094        import javax.management.ReflectionException;
0095        import javax.management.remote.JMXConnectionNotification;
0096        import javax.management.remote.JMXConnector;
0097        import javax.management.remote.JMXConnectorFactory;
0098        import javax.management.remote.JMXServiceURL;
0099        import javax.management.remote.NotificationResult;
0100        import javax.management.remote.JMXAddressable;
0101        import javax.naming.InitialContext;
0102        import javax.naming.NamingException;
0103        import javax.rmi.CORBA.Stub;
0104        import javax.rmi.PortableRemoteObject;
0105        import javax.rmi.ssl.SslRMIClientSocketFactory;
0106        import javax.security.auth.Subject;
0107        import org.omg.CORBA.BAD_OPERATION;
0108        import org.omg.CORBA.ORB;
0109        import sun.rmi.server.UnicastRef2;
0110        import sun.rmi.transport.LiveRef;
0111
0112        /**
0113         * <p>A connection to a remote RMI connector.  Usually, such
0114         * connections are made using {@link
0115         * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
0116         * However, specialized applications can use this class directly, for
0117         * example with an {@link RMIServer} stub obtained without going
0118         * through JNDI.</p>
0119         *
0120         * @since 1.5
0121         */
0122        public class RMIConnector implements  JMXConnector, Serializable,
0123                JMXAddressable {
0124
0125            private static final ClassLogger logger = new ClassLogger(
0126                    "javax.management.remote.rmi", "RMIConnector");
0127
0128            private static final long serialVersionUID = 817323035842634473L;
0129
0130            private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
0131                    Map<String, ?> environment) {
0132                if (rmiServer == null && address == null)
0133                    throw new IllegalArgumentException(
0134                            "rmiServer and jmxServiceURL both null");
0135
0136                initTransients();
0137
0138                this .rmiServer = rmiServer;
0139                this .jmxServiceURL = address;
0140                if (environment == null) {
0141                    this .env = Collections.emptyMap();
0142                } else {
0143                    EnvHelp.checkAttributes(environment);
0144                    this .env = Collections.unmodifiableMap(environment);
0145                }
0146            }
0147
0148            /**
0149             * <p>Constructs an <code>RMIConnector</code> that will connect
0150             * the RMI connector server with the given address.</p>
0151             *
0152             * <p>The address can refer directly to the connector server,
0153             * using one of the following syntaxes:</p>
0154             *
0155             * <pre>
0156             * service:jmx:rmi://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
0157             * service:jmx:iiop://<em>[host[:port]]</em>/ior/<em>encoded-IOR</em>
0158             * </pre>
0159             *
0160             * <p>(Here, the square brackets <code>[]</code> are not part of the
0161             * address but indicate that the host and port are optional.)</p>
0162             *
0163             * <p>The address can instead indicate where to find an RMI stub
0164             * through JNDI, using one of the following syntaxes:</p>
0165             *
0166             * <pre>
0167             * service:jmx:rmi://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
0168             * service:jmx:iiop://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
0169             * </pre>
0170             *
0171             * <p>An implementation may also recognize additional address
0172             * syntaxes, for example:</p>
0173             *
0174             * <pre>
0175             * service:jmx:iiop://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
0176             * </pre>
0177             *
0178             * @param url the address of the RMI connector server.
0179             *
0180             * @param environment additional attributes specifying how to make
0181             * the connection.  For JNDI-based addresses, these attributes can
0182             * usefully include JNDI attributes recognized by {@link
0183             * InitialContext#InitialContext(Hashtable) InitialContext}.  This
0184             * parameter can be null, which is equivalent to an empty Map.
0185             *
0186             * @exception IllegalArgumentException if <code>url</code>
0187             * is null.
0188             */
0189            public RMIConnector(JMXServiceURL url, Map<String, ?> environment) {
0190                this (null, url, environment);
0191            }
0192
0193            /**
0194             * <p>Constructs an <code>RMIConnector</code> using the given RMI stub.
0195             *
0196             * @param rmiServer an RMI stub representing the RMI connector server.
0197             * @param environment additional attributes specifying how to make
0198             * the connection.  This parameter can be null, which is
0199             * equivalent to an empty Map.
0200             *
0201             * @exception IllegalArgumentException if <code>rmiServer</code>
0202             * is null.
0203             */
0204            public RMIConnector(RMIServer rmiServer, Map<String, ?> environment) {
0205                this (rmiServer, null, environment);
0206            }
0207
0208            /**
0209             * <p>Returns a string representation of this object.  In general,
0210             * the <code>toString</code> method returns a string that
0211             * "textually represents" this object. The result should be a
0212             * concise but informative representation that is easy for a
0213             * person to read.</p>
0214             *
0215             * @return a String representation of this object.
0216             **/
0217            public String toString() {
0218                final StringBuilder b = new StringBuilder(this .getClass()
0219                        .getName());
0220                b.append(":");
0221                if (rmiServer != null) {
0222                    b.append(" rmiServer=").append(rmiServer.toString());
0223                }
0224                if (jmxServiceURL != null) {
0225                    if (rmiServer != null)
0226                        b.append(",");
0227                    b.append(" jmxServiceURL=")
0228                            .append(jmxServiceURL.toString());
0229                }
0230                return b.toString();
0231            }
0232
0233            /**
0234             * <p>The address of this connector.</p>
0235             *
0236             * @return the address of this connector, or null if it
0237             * does not have one.
0238             *
0239             * @since 1.6
0240             */
0241            public JMXServiceURL getAddress() {
0242                return jmxServiceURL;
0243            }
0244
0245            //--------------------------------------------------------------------
0246            // implements JMXConnector interface
0247            //--------------------------------------------------------------------
0248            public void connect() throws IOException {
0249                connect(null);
0250            }
0251
0252            public synchronized void connect(Map<String, ?> environment)
0253                    throws IOException {
0254                final boolean tracing = logger.traceOn();
0255                String idstr = (tracing ? "[" + this .toString() + "]" : null);
0256
0257                if (terminated) {
0258                    logger.trace("connect", idstr + " already closed.");
0259                    throw new IOException("Connector closed");
0260                }
0261                if (connected) {
0262                    logger.trace("connect", idstr + " already connected.");
0263                    return;
0264                }
0265
0266                try {
0267                    if (tracing)
0268                        logger.trace("connect", idstr + " connecting...");
0269
0270                    final Map<String, Object> usemap = new HashMap<String, Object>(
0271                            (this .env == null) ? Collections
0272                                    .<String, Object> emptyMap() : this .env);
0273
0274                    if (environment != null) {
0275                        EnvHelp.checkAttributes(environment);
0276                        usemap.putAll(environment);
0277                    }
0278
0279                    // Get RMIServer stub from directory or URL encoding if needed.
0280                    if (tracing)
0281                        logger.trace("connect", idstr + " finding stub...");
0282                    RMIServer stub = (rmiServer != null) ? rmiServer
0283                            : findRMIServer(jmxServiceURL, usemap);
0284
0285                    // Check for secure RMIServer stub if the corresponding
0286                    // client-side environment property is set to "true".
0287                    //
0288                    boolean checkStub = EnvHelp.computeBooleanFromString(
0289                            usemap, "jmx.remote.x.check.stub");
0290                    if (checkStub)
0291                        checkStub(stub, rmiServerImplStubClass);
0292
0293                    // Connect IIOP Stub if needed.
0294                    if (tracing)
0295                        logger.trace("connect", idstr + " connecting stub...");
0296                    stub = connectStub(stub, usemap);
0297                    idstr = (tracing ? "[" + this .toString() + "]" : null);
0298
0299                    // Calling newClient on the RMIServer stub.
0300                    if (tracing)
0301                        logger.trace("connect", idstr
0302                                + " getting connection...");
0303                    Object credentials = usemap.get(CREDENTIALS);
0304                    connection = getConnection(stub, credentials, checkStub);
0305
0306                    // Always use one of:
0307                    //   ClassLoader provided in Map at connect time,
0308                    //   or contextClassLoader at connect time.
0309                    if (tracing)
0310                        logger.trace("connect", idstr
0311                                + " getting class loader...");
0312                    defaultClassLoader = EnvHelp
0313                            .resolveClientClassLoader(usemap);
0314
0315                    usemap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
0316                            defaultClassLoader);
0317
0318                    rmiNotifClient = new RMINotifClient(defaultClassLoader,
0319                            usemap);
0320
0321                    env = usemap;
0322                    final long checkPeriod = EnvHelp
0323                            .getConnectionCheckPeriod(usemap);
0324                    communicatorAdmin = new RMIClientCommunicatorAdmin(
0325                            checkPeriod);
0326
0327                    connected = true;
0328
0329                    // The connectionId variable is used in doStart(), when
0330                    // reconnecting, to identify the "old" connection.
0331                    //
0332                    connectionId = getConnectionId();
0333
0334                    Notification connectedNotif = new JMXConnectionNotification(
0335                            JMXConnectionNotification.OPENED, this ,
0336                            connectionId, clientNotifSeqNo++,
0337                            "Successful connection", null);
0338                    sendNotification(connectedNotif);
0339
0340                    if (tracing)
0341                        logger.trace("connect", idstr + " done...");
0342                } catch (IOException e) {
0343                    if (tracing)
0344                        logger.trace("connect", idstr + " failed to connect: "
0345                                + e);
0346                    throw e;
0347                } catch (RuntimeException e) {
0348                    if (tracing)
0349                        logger.trace("connect", idstr + " failed to connect: "
0350                                + e);
0351                    throw e;
0352                } catch (NamingException e) {
0353                    final String msg = "Failed to retrieve RMIServer stub: "
0354                            + e;
0355                    if (tracing)
0356                        logger.trace("connect", idstr + " " + msg);
0357                    throw EnvHelp.initCause(new IOException(msg), e);
0358                }
0359            }
0360
0361            public synchronized String getConnectionId() throws IOException {
0362                if (terminated || !connected) {
0363                    if (logger.traceOn())
0364                        logger.trace("getConnectionId", "[" + this .toString()
0365                                + "] not connected.");
0366
0367                    throw new IOException("Not connected");
0368                }
0369
0370                // we do a remote call to have an IOException if the connection is broken.
0371                // see the bug 4939578
0372                return connection.getConnectionId();
0373            }
0374
0375            public synchronized MBeanServerConnection getMBeanServerConnection()
0376                    throws IOException {
0377                return getMBeanServerConnection(null);
0378            }
0379
0380            public synchronized MBeanServerConnection getMBeanServerConnection(
0381                    Subject delegationSubject) throws IOException {
0382
0383                if (terminated) {
0384                    if (logger.traceOn())
0385                        logger.trace("getMBeanServerConnection", "["
0386                                + this .toString() + "] already closed.");
0387                    throw new IOException("Connection closed");
0388                } else if (!connected) {
0389                    if (logger.traceOn())
0390                        logger.trace("getMBeanServerConnection", "["
0391                                + this .toString() + "] is not connected.");
0392                    throw new IOException("Not connected");
0393                }
0394
0395                MBeanServerConnection mbsc = rmbscMap.get(delegationSubject);
0396                if (mbsc != null)
0397                    return mbsc;
0398
0399                mbsc = new RemoteMBeanServerConnection(delegationSubject);
0400                rmbscMap.put(delegationSubject, mbsc);
0401                return mbsc;
0402            }
0403
0404            public void addConnectionNotificationListener(
0405                    NotificationListener listener, NotificationFilter filter,
0406                    Object handback) {
0407                if (listener == null)
0408                    throw new NullPointerException("listener");
0409                connectionBroadcaster.addNotificationListener(listener, filter,
0410                        handback);
0411            }
0412
0413            public void removeConnectionNotificationListener(
0414                    NotificationListener listener)
0415                    throws ListenerNotFoundException {
0416                if (listener == null)
0417                    throw new NullPointerException("listener");
0418                connectionBroadcaster.removeNotificationListener(listener);
0419            }
0420
0421            public void removeConnectionNotificationListener(
0422                    NotificationListener listener, NotificationFilter filter,
0423                    Object handback) throws ListenerNotFoundException {
0424                if (listener == null)
0425                    throw new NullPointerException("listener");
0426                connectionBroadcaster.removeNotificationListener(listener,
0427                        filter, handback);
0428            }
0429
0430            private void sendNotification(Notification n) {
0431                connectionBroadcaster.sendNotification(n);
0432            }
0433
0434            public synchronized void close() throws IOException {
0435                close(false);
0436            }
0437
0438            // allows to do close after setting the flag "terminated" to true.
0439            // It is necessary to avoid a deadlock, see 6296324
0440            private synchronized void close(boolean intern) throws IOException {
0441                final boolean tracing = logger.traceOn();
0442                final boolean debug = logger.debugOn();
0443                final String idstr = (tracing ? "[" + this .toString() + "]"
0444                        : null);
0445
0446                if (!intern) {
0447                    // Return if already cleanly closed.
0448                    //
0449                    if (terminated) {
0450                        if (closeException == null) {
0451                            if (tracing)
0452                                logger.trace("close", idstr
0453                                        + " already closed.");
0454                            return;
0455                        }
0456                    } else {
0457                        terminated = true;
0458                    }
0459                }
0460
0461                if (closeException != null && tracing) {
0462                    // Already closed, but not cleanly. Attempt again.
0463                    //
0464                    if (tracing) {
0465                        logger.trace("close", idstr + " had failed: "
0466                                + closeException);
0467                        logger.trace("close", idstr
0468                                + " attempting to close again.");
0469                    }
0470                }
0471
0472                String savedConnectionId = null;
0473                if (connected) {
0474                    savedConnectionId = connectionId;
0475                }
0476
0477                closeException = null;
0478
0479                if (tracing)
0480                    logger.trace("close", idstr + " closing.");
0481
0482                if (communicatorAdmin != null) {
0483                    communicatorAdmin.terminate();
0484                }
0485
0486                if (rmiNotifClient != null) {
0487                    try {
0488                        rmiNotifClient.terminate();
0489                        if (tracing)
0490                            logger.trace("close", idstr
0491                                    + " RMI Notification client terminated.");
0492                    } catch (RuntimeException x) {
0493                        closeException = x;
0494                        if (tracing)
0495                            logger
0496                                    .trace(
0497                                            "close",
0498                                            idstr
0499                                                    + " Failed to terminate RMI Notification client: "
0500                                                    + x);
0501                        if (debug)
0502                            logger.debug("close", x);
0503                    }
0504                }
0505
0506                if (connection != null) {
0507                    try {
0508                        connection.close();
0509                        if (tracing)
0510                            logger.trace("close", idstr + " closed.");
0511                    } catch (NoSuchObjectException nse) {
0512                        // OK, the server maybe closed itself.
0513                    } catch (IOException e) {
0514                        closeException = e;
0515                        if (tracing)
0516                            logger.trace("close", idstr
0517                                    + " Failed to close RMIServer: " + e);
0518                        if (debug)
0519                            logger.debug("close", e);
0520                    }
0521                }
0522
0523                // Clean up MBeanServerConnection table
0524                //
0525                rmbscMap.clear();
0526
0527                /* Send notification of closure.  We don't do this if the user
0528                 * never called connect() on the connector, because there's no
0529                 * connection id in that case.  */
0530
0531                if (savedConnectionId != null) {
0532                    Notification closedNotif = new JMXConnectionNotification(
0533                            JMXConnectionNotification.CLOSED, this ,
0534                            savedConnectionId, clientNotifSeqNo++,
0535                            "Client has been closed", null);
0536                    sendNotification(closedNotif);
0537                }
0538
0539                // throw exception if needed
0540                //
0541                if (closeException != null) {
0542                    if (tracing)
0543                        logger.trace("close", idstr + " failed to close: "
0544                                + closeException);
0545                    if (closeException instanceof  IOException)
0546                        throw (IOException) closeException;
0547                    if (closeException instanceof  RuntimeException)
0548                        throw (RuntimeException) closeException;
0549                    final IOException x = new IOException("Failed to close: "
0550                            + closeException);
0551                    throw EnvHelp.initCause(x, closeException);
0552                }
0553            }
0554
0555            // added for re-connection
0556            private Integer addListenerWithSubject(ObjectName name,
0557                    MarshalledObject filter, Subject delegationSubject,
0558                    boolean reconnect) throws InstanceNotFoundException,
0559                    IOException {
0560
0561                final boolean debug = logger.debugOn();
0562                if (debug)
0563                    logger.debug("addListenerWithSubject",
0564                            "(ObjectName,MarshalledObject,Subject)");
0565
0566                final ObjectName[] names = new ObjectName[] { name };
0567                final MarshalledObject[] filters = new MarshalledObject[] { filter };
0568                final Subject[] delegationSubjects = new Subject[] { delegationSubject };
0569
0570                final Integer[] listenerIDs = addListenersWithSubjects(names,
0571                        filters, delegationSubjects, reconnect);
0572
0573                if (debug)
0574                    logger.debug("addListenerWithSubject", "listenerID="
0575                            + listenerIDs[0]);
0576                return listenerIDs[0];
0577            }
0578
0579            // added for re-connection
0580            private Integer[] addListenersWithSubjects(ObjectName[] names,
0581                    MarshalledObject[] filters, Subject[] delegationSubjects,
0582                    boolean reconnect) throws InstanceNotFoundException,
0583                    IOException {
0584
0585                final boolean debug = logger.debugOn();
0586                if (debug)
0587                    logger.debug("addListenersWithSubjects",
0588                            "(ObjectName[],MarshalledObject[],Subject[])");
0589
0590                final ClassLoader old = pushDefaultClassLoader();
0591                Integer[] listenerIDs = null;
0592
0593                try {
0594                    listenerIDs = connection.addNotificationListeners(names,
0595                            filters, delegationSubjects);
0596                } catch (NoSuchObjectException noe) {
0597                    // maybe reconnect
0598                    if (reconnect) {
0599                        communicatorAdmin.gotIOException(noe);
0600
0601                        listenerIDs = connection.addNotificationListeners(
0602                                names, filters, delegationSubjects);
0603                    } else {
0604                        throw noe;
0605                    }
0606                } catch (IOException ioe) {
0607                    // send a failed notif if necessary
0608                    communicatorAdmin.gotIOException(ioe);
0609                } finally {
0610                    popDefaultClassLoader(old);
0611                }
0612
0613                if (debug)
0614                    logger.debug("addListenersWithSubjects", "registered "
0615                            + listenerIDs.length + " listener(s)");
0616                return listenerIDs;
0617            }
0618
0619            //--------------------------------------------------------------------
0620            // Implementation of MBeanServerConnection
0621            //--------------------------------------------------------------------
0622            private class RemoteMBeanServerConnection implements 
0623                    MBeanServerConnection {
0624
0625                private Subject delegationSubject;
0626
0627                public RemoteMBeanServerConnection() {
0628                    this (null);
0629                }
0630
0631                public RemoteMBeanServerConnection(Subject delegationSubject) {
0632                    this .delegationSubject = delegationSubject;
0633                }
0634
0635                public ObjectInstance createMBean(String className,
0636                        ObjectName name) throws ReflectionException,
0637                        InstanceAlreadyExistsException,
0638                        MBeanRegistrationException, MBeanException,
0639                        NotCompliantMBeanException, IOException {
0640                    if (logger.debugOn())
0641                        logger.debug("createMBean(String,ObjectName)",
0642                                "className=" + className + ", name=" + name);
0643
0644                    final ClassLoader old = pushDefaultClassLoader();
0645                    try {
0646                        return connection.createMBean(className, name,
0647                                delegationSubject);
0648                    } catch (IOException ioe) {
0649                        communicatorAdmin.gotIOException(ioe);
0650
0651                        return connection.createMBean(className, name,
0652                                delegationSubject);
0653                    } finally {
0654                        popDefaultClassLoader(old);
0655                    }
0656                }
0657
0658                public ObjectInstance createMBean(String className,
0659                        ObjectName name, ObjectName loaderName)
0660                        throws ReflectionException,
0661                        InstanceAlreadyExistsException,
0662                        MBeanRegistrationException, MBeanException,
0663                        NotCompliantMBeanException, InstanceNotFoundException,
0664                        IOException {
0665
0666                    if (logger.debugOn())
0667                        logger.debug(
0668                                "createMBean(String,ObjectName,ObjectName)",
0669                                "className=" + className + ", name=" + name
0670                                        + ", loaderName=" + loaderName + ")");
0671
0672                    final ClassLoader old = pushDefaultClassLoader();
0673                    try {
0674                        return connection.createMBean(className, name,
0675                                loaderName, delegationSubject);
0676
0677                    } catch (IOException ioe) {
0678                        communicatorAdmin.gotIOException(ioe);
0679
0680                        return connection.createMBean(className, name,
0681                                loaderName, delegationSubject);
0682
0683                    } finally {
0684                        popDefaultClassLoader(old);
0685                    }
0686                }
0687
0688                public ObjectInstance createMBean(String className,
0689                        ObjectName name, Object params[], String signature[])
0690                        throws ReflectionException,
0691                        InstanceAlreadyExistsException,
0692                        MBeanRegistrationException, MBeanException,
0693                        NotCompliantMBeanException, IOException {
0694                    if (logger.debugOn())
0695                        logger
0696                                .debug(
0697                                        "createMBean(String,ObjectName,Object[],String[])",
0698                                        "className=" + className + ", name="
0699                                                + name + ", params="
0700                                                + objects(params)
0701                                                + ", signature="
0702                                                + strings(signature));
0703
0704                    final MarshalledObject<Object[]> sParams = new MarshalledObject<Object[]>(
0705                            params);
0706                    final ClassLoader old = pushDefaultClassLoader();
0707                    try {
0708                        return connection.createMBean(className, name, sParams,
0709                                signature, delegationSubject);
0710                    } catch (IOException ioe) {
0711                        communicatorAdmin.gotIOException(ioe);
0712
0713                        return connection.createMBean(className, name, sParams,
0714                                signature, delegationSubject);
0715                    } finally {
0716                        popDefaultClassLoader(old);
0717                    }
0718                }
0719
0720                public ObjectInstance createMBean(String className,
0721                        ObjectName name, ObjectName loaderName,
0722                        Object params[], String signature[])
0723                        throws ReflectionException,
0724                        InstanceAlreadyExistsException,
0725                        MBeanRegistrationException, MBeanException,
0726                        NotCompliantMBeanException, InstanceNotFoundException,
0727                        IOException {
0728                    if (logger.debugOn())
0729                        logger
0730                                .debug(
0731                                        "createMBean(String,ObjectName,ObjectName,Object[],String[])",
0732                                        "className=" + className + ", name="
0733                                                + name + ", loaderName="
0734                                                + loaderName + ", params="
0735                                                + objects(params)
0736                                                + ", signature="
0737                                                + strings(signature));
0738
0739                    final MarshalledObject<Object[]> sParams = new MarshalledObject<Object[]>(
0740                            params);
0741                    final ClassLoader old = pushDefaultClassLoader();
0742                    try {
0743                        return connection.createMBean(className, name,
0744                                loaderName, sParams, signature,
0745                                delegationSubject);
0746                    } catch (IOException ioe) {
0747                        communicatorAdmin.gotIOException(ioe);
0748
0749                        return connection.createMBean(className, name,
0750                                loaderName, sParams, signature,
0751                                delegationSubject);
0752                    } finally {
0753                        popDefaultClassLoader(old);
0754                    }
0755                }
0756
0757                public void unregisterMBean(ObjectName name)
0758                        throws InstanceNotFoundException,
0759                        MBeanRegistrationException, IOException {
0760                    if (logger.debugOn())
0761                        logger.debug("unregisterMBean", "name=" + name);
0762
0763                    final ClassLoader old = pushDefaultClassLoader();
0764                    try {
0765                        connection.unregisterMBean(name, delegationSubject);
0766                    } catch (IOException ioe) {
0767                        communicatorAdmin.gotIOException(ioe);
0768
0769                        connection.unregisterMBean(name, delegationSubject);
0770                    } finally {
0771                        popDefaultClassLoader(old);
0772                    }
0773                }
0774
0775                public ObjectInstance getObjectInstance(ObjectName name)
0776                        throws InstanceNotFoundException, IOException {
0777                    if (logger.debugOn())
0778                        logger.debug("getObjectInstance", "name=" + name);
0779
0780                    final ClassLoader old = pushDefaultClassLoader();
0781                    try {
0782                        return connection.getObjectInstance(name,
0783                                delegationSubject);
0784                    } catch (IOException ioe) {
0785                        communicatorAdmin.gotIOException(ioe);
0786
0787                        return connection.getObjectInstance(name,
0788                                delegationSubject);
0789                    } finally {
0790                        popDefaultClassLoader(old);
0791                    }
0792                }
0793
0794                public Set<ObjectInstance> queryMBeans(ObjectName name,
0795                        QueryExp query) throws IOException {
0796                    if (logger.debugOn())
0797                        logger.debug("queryMBeans", "name=" + name + ", query="
0798                                + query);
0799
0800                    final MarshalledObject<QueryExp> sQuery = new MarshalledObject<QueryExp>(
0801                            query);
0802                    final ClassLoader old = pushDefaultClassLoader();
0803                    try {
0804                        return connection.queryMBeans(name, sQuery,
0805                                delegationSubject);
0806                    } catch (IOException ioe) {
0807                        communicatorAdmin.gotIOException(ioe);
0808
0809                        return connection.queryMBeans(name, sQuery,
0810                                delegationSubject);
0811                    } finally {
0812                        popDefaultClassLoader(old);
0813                    }
0814                }
0815
0816                public Set<ObjectName> queryNames(ObjectName name,
0817                        QueryExp query) throws IOException {
0818                    if (logger.debugOn())
0819                        logger.debug("queryNames", "name=" + name + ", query="
0820                                + query);
0821
0822                    final MarshalledObject<QueryExp> sQuery = new MarshalledObject<QueryExp>(
0823                            query);
0824                    final ClassLoader old = pushDefaultClassLoader();
0825                    try {
0826                        return connection.queryNames(name, sQuery,
0827                                delegationSubject);
0828                    } catch (IOException ioe) {
0829                        communicatorAdmin.gotIOException(ioe);
0830
0831                        return connection.queryNames(name, sQuery,
0832                                delegationSubject);
0833                    } finally {
0834                        popDefaultClassLoader(old);
0835                    }
0836                }
0837
0838                public boolean isRegistered(ObjectName name) throws IOException {
0839                    if (logger.debugOn())
0840                        logger.debug("isRegistered", "name=" + name);
0841
0842                    final ClassLoader old = pushDefaultClassLoader();
0843                    try {
0844                        return connection.isRegistered(name, delegationSubject);
0845                    } catch (IOException ioe) {
0846                        communicatorAdmin.gotIOException(ioe);
0847
0848                        return connection.isRegistered(name, delegationSubject);
0849                    } finally {
0850                        popDefaultClassLoader(old);
0851                    }
0852                }
0853
0854                public Integer getMBeanCount() throws IOException {
0855                    if (logger.debugOn())
0856                        logger.debug("getMBeanCount", "");
0857
0858                    final ClassLoader old = pushDefaultClassLoader();
0859                    try {
0860                        return connection.getMBeanCount(delegationSubject);
0861                    } catch (IOException ioe) {
0862                        communicatorAdmin.gotIOException(ioe);
0863
0864                        return connection.getMBeanCount(delegationSubject);
0865                    } finally {
0866                        popDefaultClassLoader(old);
0867                    }
0868                }
0869
0870                public Object getAttribute(ObjectName name, String attribute)
0871                        throws MBeanException, AttributeNotFoundException,
0872                        InstanceNotFoundException, ReflectionException,
0873                        IOException {
0874                    if (logger.debugOn())
0875                        logger.debug("getAttribute", "name=" + name
0876                                + ", attribute=" + attribute);
0877
0878                    final ClassLoader old = pushDefaultClassLoader();
0879                    try {
0880                        return connection.getAttribute(name, attribute,
0881                                delegationSubject);
0882                    } catch (IOException ioe) {
0883                        communicatorAdmin.gotIOException(ioe);
0884
0885                        return connection.getAttribute(name, attribute,
0886                                delegationSubject);
0887                    } finally {
0888                        popDefaultClassLoader(old);
0889                    }
0890                }
0891
0892                public AttributeList getAttributes(ObjectName name,
0893                        String[] attributes) throws InstanceNotFoundException,
0894                        ReflectionException, IOException {
0895                    if (logger.debugOn())
0896                        logger.debug("getAttributes", "name=" + name
0897                                + ", attributes=" + strings(attributes));
0898
0899                    final ClassLoader old = pushDefaultClassLoader();
0900                    try {
0901                        return connection.getAttributes(name, attributes,
0902                                delegationSubject);
0903
0904                    } catch (IOException ioe) {
0905                        communicatorAdmin.gotIOException(ioe);
0906
0907                        return connection.getAttributes(name, attributes,
0908                                delegationSubject);
0909                    } finally {
0910                        popDefaultClassLoader(old);
0911                    }
0912                }
0913
0914                public void setAttribute(ObjectName name, Attribute attribute)
0915                        throws InstanceNotFoundException,
0916                        AttributeNotFoundException,
0917                        InvalidAttributeValueException, MBeanException,
0918                        ReflectionException, IOException {
0919
0920                    if (logger.debugOn())
0921                        logger.debug("setAttribute", "name=" + name
0922                                + ", attribute=" + attribute);
0923
0924                    final MarshalledObject<Attribute> sAttribute = new MarshalledObject<Attribute>(
0925                            attribute);
0926                    final ClassLoader old = pushDefaultClassLoader();
0927                    try {
0928                        connection.setAttribute(name, sAttribute,
0929                                delegationSubject);
0930                    } catch (IOException ioe) {
0931                        communicatorAdmin.gotIOException(ioe);
0932
0933                        connection.setAttribute(name, sAttribute,
0934                                delegationSubject);
0935                    } finally {
0936                        popDefaultClassLoader(old);
0937                    }
0938                }
0939
0940                public AttributeList setAttributes(ObjectName name,
0941                        AttributeList attributes)
0942                        throws InstanceNotFoundException, ReflectionException,
0943                        IOException {
0944
0945                    if (logger.debugOn())
0946                        logger.debug("setAttributes", "name=" + name
0947                                + ", attributes=" + attributes);
0948
0949                    final MarshalledObject<AttributeList> sAttributes = new MarshalledObject<AttributeList>(
0950                            attributes);
0951                    final ClassLoader old = pushDefaultClassLoader();
0952                    try {
0953                        return connection.setAttributes(name, sAttributes,
0954                                delegationSubject);
0955                    } catch (IOException ioe) {
0956                        communicatorAdmin.gotIOException(ioe);
0957
0958                        return connection.setAttributes(name, sAttributes,
0959                                delegationSubject);
0960                    } finally {
0961                        popDefaultClassLoader(old);
0962                    }
0963                }
0964
0965                public Object invoke(ObjectName name, String operationName,
0966                        Object params[], String signature[])
0967                        throws InstanceNotFoundException, MBeanException,
0968                        ReflectionException, IOException {
0969
0970                    if (logger.debugOn())
0971                        logger.debug("invoke", "name=" + name
0972                                + ", operationName=" + operationName
0973                                + ", params=" + objects(params)
0974                                + ", signature=" + strings(signature));
0975
0976                    final MarshalledObject<Object[]> sParams = new MarshalledObject<Object[]>(
0977                            params);
0978                    final ClassLoader old = pushDefaultClassLoader();
0979                    try {
0980                        return connection.invoke(name, operationName, sParams,
0981                                signature, delegationSubject);
0982                    } catch (IOException ioe) {
0983                        communicatorAdmin.gotIOException(ioe);
0984
0985                        return connection.invoke(name, operationName, sParams,
0986                                signature, delegationSubject);
0987                    } finally {
0988                        popDefaultClassLoader(old);
0989                    }
0990                }
0991
0992                public String getDefaultDomain() throws IOException {
0993                    if (logger.debugOn())
0994                        logger.debug("getDefaultDomain", "");
0995
0996                    final ClassLoader old = pushDefaultClassLoader();
0997                    try {
0998                        return connection.getDefaultDomain(delegationSubject);
0999                    } catch (IOException ioe) {
1000                        communicatorAdmin.gotIOException(ioe);
1001
1002                        return connection.getDefaultDomain(delegationSubject);
1003                    } finally {
1004                        popDefaultClassLoader(old);
1005                    }
1006                }
1007
1008                public String[] getDomains() throws IOException {
1009                    if (logger.debugOn())
1010                        logger.debug("getDomains", "");
1011
1012                    final ClassLoader old = pushDefaultClassLoader();
1013                    try {
1014                        return connection.getDomains(delegationSubject);
1015                    } catch (IOException ioe) {
1016                        communicatorAdmin.gotIOException(ioe);
1017
1018                        return connection.getDomains(delegationSubject);
1019                    } finally {
1020                        popDefaultClassLoader(old);
1021                    }
1022                }
1023
1024                public MBeanInfo getMBeanInfo(ObjectName name)
1025                        throws InstanceNotFoundException,
1026                        IntrospectionException, ReflectionException,
1027                        IOException {
1028
1029                    if (logger.debugOn())
1030                        logger.debug("getMBeanInfo", "name=" + name);
1031                    final ClassLoader old = pushDefaultClassLoader();
1032                    try {
1033                        return connection.getMBeanInfo(name, delegationSubject);
1034                    } catch (IOException ioe) {
1035                        communicatorAdmin.gotIOException(ioe);
1036
1037                        return connection.getMBeanInfo(name, delegationSubject);
1038                    } finally {
1039                        popDefaultClassLoader(old);
1040                    }
1041                }
1042
1043                public boolean isInstanceOf(ObjectName name, String className)
1044                        throws InstanceNotFoundException, IOException {
1045                    if (logger.debugOn())
1046                        logger.debug("isInstanceOf", "name=" + name
1047                                + ", className=" + className);
1048
1049                    final ClassLoader old = pushDefaultClassLoader();
1050                    try {
1051                        return connection.isInstanceOf(name, className,
1052                                delegationSubject);
1053                    } catch (IOException ioe) {
1054                        communicatorAdmin.gotIOException(ioe);
1055
1056                        return connection.isInstanceOf(name, className,
1057                                delegationSubject);
1058                    } finally {
1059                        popDefaultClassLoader(old);
1060                    }
1061                }
1062
1063                public void addNotificationListener(ObjectName name,
1064                        ObjectName listener, NotificationFilter filter,
1065                        Object handback) throws InstanceNotFoundException,
1066                        IOException {
1067
1068                    if (logger.debugOn())
1069                        logger
1070                                .debug(
1071                                        "addNotificationListener"
1072                                                + "(ObjectName,ObjectName,NotificationFilter,Object)",
1073                                        "name=" + name + ", listener="
1074                                                + listener + ", filter="
1075                                                + filter + ", handback="
1076                                                + handback);
1077
1078                    final MarshalledObject<NotificationFilter> sFilter = new MarshalledObject<NotificationFilter>(
1079                            filter);
1080                    final MarshalledObject<Object> sHandback = new MarshalledObject<Object>(
1081                            handback);
1082                    final ClassLoader old = pushDefaultClassLoader();
1083                    try {
1084                        connection.addNotificationListener(name, listener,
1085                                sFilter, sHandback, delegationSubject);
1086                    } catch (IOException ioe) {
1087                        communicatorAdmin.gotIOException(ioe);
1088
1089                        connection.addNotificationListener(name, listener,
1090                                sFilter, sHandback, delegationSubject);
1091                    } finally {
1092                        popDefaultClassLoader(old);
1093                    }
1094                }
1095
1096                public void removeNotificationListener(ObjectName name,
1097                        ObjectName listener) throws InstanceNotFoundException,
1098                        ListenerNotFoundException, IOException {
1099
1100                    if (logger.debugOn())
1101                        logger.debug("removeNotificationListener"
1102                                + "(ObjectName,ObjectName)", "name=" + name
1103                                + ", listener=" + listener);
1104
1105                    final ClassLoader old = pushDefaultClassLoader();
1106                    try {
1107                        connection.removeNotificationListener(name, listener,
1108                                delegationSubject);
1109                    } catch (IOException ioe) {
1110                        communicatorAdmin.gotIOException(ioe);
1111
1112                        connection.removeNotificationListener(name, listener,
1113                                delegationSubject);
1114                    } finally {
1115                        popDefaultClassLoader(old);
1116                    }
1117                }
1118
1119                public void removeNotificationListener(ObjectName name,
1120                        ObjectName listener, NotificationFilter filter,
1121                        Object handback) throws InstanceNotFoundException,
1122                        ListenerNotFoundException, IOException {
1123                    if (logger.debugOn())
1124                        logger
1125                                .debug(
1126                                        "removeNotificationListener"
1127                                                + "(ObjectName,ObjectName,NotificationFilter,Object)",
1128                                        "name=" + name + ", listener="
1129                                                + listener + ", filter="
1130                                                + filter + ", handback="
1131                                                + handback);
1132
1133                    final MarshalledObject<NotificationFilter> sFilter = new MarshalledObject<NotificationFilter>(
1134                            filter);
1135                    final MarshalledObject<Object> sHandback = new MarshalledObject<Object>(
1136                            handback);
1137                    final ClassLoader old = pushDefaultClassLoader();
1138                    try {
1139                        connection.removeNotificationListener(name, listener,
1140                                sFilter, sHandback, delegationSubject);
1141                    } catch (IOException ioe) {
1142                        communicatorAdmin.gotIOException(ioe);
1143
1144                        connection.removeNotificationListener(name, listener,
1145                                sFilter, sHandback, delegationSubject);
1146                    } finally {
1147                        popDefaultClassLoader(old);
1148                    }
1149                }
1150
1151                // Specific Notification Handle ----------------------------------
1152
1153                public void addNotificationListener(ObjectName name,
1154                        NotificationListener listener,
1155                        NotificationFilter filter, Object handback)
1156                        throws InstanceNotFoundException, IOException {
1157
1158                    final boolean debug = logger.debugOn();
1159                    if (debug)
1160                        logger.debug("addNotificationListener"
1161                                + "(ObjectName,NotificationListener,"
1162                                + "NotificationFilter,Object)", "name=" + name
1163                                + ", listener=" + listener + ", filter="
1164                                + filter + ", handback=" + handback);
1165
1166                    final Integer listenerID = addListenerWithSubject(name,
1167                            new MarshalledObject<NotificationFilter>(filter),
1168                            delegationSubject, true);
1169                    rmiNotifClient.addNotificationListener(listenerID, name,
1170                            listener, filter, handback, delegationSubject);
1171                }
1172
1173                public void removeNotificationListener(ObjectName name,
1174                        NotificationListener listener)
1175                        throws InstanceNotFoundException,
1176                        ListenerNotFoundException, IOException {
1177                    final boolean debug = logger.debugOn();
1178
1179                    if (debug)
1180                        logger.debug("removeNotificationListener"
1181                                + "(ObjectName,NotificationListener)", "name="
1182                                + name + ", listener=" + listener);
1183
1184                    final Integer[] ret = rmiNotifClient
1185                            .removeNotificationListener(name, listener);
1186
1187                    if (debug)
1188                        logger.debug("removeNotificationListener",
1189                                "listenerIDs=" + objects(ret));
1190
1191                    final ClassLoader old = pushDefaultClassLoader();
1192
1193                    try {
1194                        connection.removeNotificationListeners(name, ret,
1195                                delegationSubject);
1196                    } catch (IOException ioe) {
1197                        communicatorAdmin.gotIOException(ioe);
1198
1199                        connection.removeNotificationListeners(name, ret,
1200                                delegationSubject);
1201                    } finally {
1202                        popDefaultClassLoader(old);
1203                    }
1204
1205                }
1206
1207                public void removeNotificationListener(ObjectName name,
1208                        NotificationListener listener,
1209                        NotificationFilter filter, Object handback)
1210                        throws InstanceNotFoundException,
1211                        ListenerNotFoundException, IOException {
1212                    final boolean debug = logger.debugOn();
1213
1214                    if (debug)
1215                        logger.debug("removeNotificationListener"
1216                                + "(ObjectName,NotificationListener,"
1217                                + "NotificationFilter,Object)", "name=" + name
1218                                + ", listener=" + listener + ", filter="
1219                                + filter + ", handback=" + handback);
1220
1221                    final Integer ret = rmiNotifClient
1222                            .removeNotificationListener(name, listener, filter,
1223                                    handback);
1224
1225                    if (debug)
1226                        logger.debug("removeNotificationListener",
1227                                "listenerID=" + ret);
1228
1229                    final ClassLoader old = pushDefaultClassLoader();
1230                    try {
1231                        connection.removeNotificationListeners(name,
1232                                new Integer[] { ret }, delegationSubject);
1233                    } catch (IOException ioe) {
1234                        communicatorAdmin.gotIOException(ioe);
1235
1236                        connection.removeNotificationListeners(name,
1237                                new Integer[] { ret }, delegationSubject);
1238                    } finally {
1239                        popDefaultClassLoader(old);
1240                    }
1241
1242                }
1243            }
1244
1245            //--------------------------------------------------------------------
1246            private class RMINotifClient extends ClientNotifForwarder {
1247                public RMINotifClient(ClassLoader cl, Map env) {
1248                    super (cl, env);
1249                }
1250
1251                protected NotificationResult fetchNotifs(
1252                        long clientSequenceNumber, int maxNotifications,
1253                        long timeout) throws IOException,
1254                        ClassNotFoundException {
1255                    IOException org;
1256
1257                    while (true) { // used for a successful re-connection
1258                        try {
1259                            return connection.fetchNotifications(
1260                                    clientSequenceNumber, maxNotifications,
1261                                    timeout);
1262                        } catch (IOException ioe) {
1263                            org = ioe;
1264
1265                            // inform of IOException
1266                            try {
1267                                communicatorAdmin.gotIOException(ioe);
1268
1269                                // The connection should be re-established.
1270                                continue;
1271                            } catch (IOException ee) {
1272                                // No more fetch, the Exception will be re-thrown.
1273                                break;
1274                            } // never reached
1275                        } // never reached
1276                    }
1277
1278                    // specially treating for an UnmarshalException
1279                    if (org instanceof  UnmarshalException) {
1280                        UnmarshalException ume = (UnmarshalException) org;
1281
1282                        if (ume.detail instanceof  ClassNotFoundException)
1283                            throw (ClassNotFoundException) ume.detail;
1284
1285                        /* In Sun's RMI implementation, if a method return
1286                           contains an unserializable object, then we get
1287                           UnmarshalException wrapping WriteAbortedException
1288                           wrapping NotSerializableException.  In that case we
1289                           extract the NotSerializableException so that our
1290                           caller can realize it should try to skip past the
1291                           notification that presumably caused it.  It's not
1292                           certain that every other RMI implementation will
1293                           generate this exact exception sequence.  If not, we
1294                           will not detect that the problem is due to an
1295                           unserializable object, and we will stop trying to
1296                           receive notifications from the server.  It's not
1297                           clear we can do much better.  */
1298                        if (ume.detail instanceof  WriteAbortedException) {
1299                            WriteAbortedException wae = (WriteAbortedException) ume.detail;
1300                            if (wae.detail instanceof  IOException)
1301                                throw (IOException) wae.detail;
1302                        }
1303                    } else if (org instanceof  MarshalException) {
1304                        // IIOP will throw MarshalException wrapping a NotSerializableException
1305                        // when a server fails to serialize a response.
1306                        MarshalException me = (MarshalException) org;
1307                        if (me.detail instanceof  NotSerializableException) {
1308                            throw (NotSerializableException) me.detail;
1309                        }
1310                    }
1311
1312                    // Not serialization problem, simply re-throw the orginal exception
1313                    throw org;
1314                }
1315
1316                protected Integer addListenerForMBeanRemovedNotif()
1317                        throws IOException, InstanceNotFoundException {
1318                    MarshalledObject<NotificationFilter> sFilter = null;
1319                    NotificationFilterSupport clientFilter = new NotificationFilterSupport();
1320                    clientFilter
1321                            .enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
1322                    sFilter = new MarshalledObject<NotificationFilter>(
1323                            clientFilter);
1324
1325                    Integer[] listenerIDs;
1326                    final ObjectName[] names = new ObjectName[] { MBeanServerDelegate.DELEGATE_NAME };
1327                    final MarshalledObject[] filters = new MarshalledObject[] { sFilter };
1328                    final Subject[] subjects = new Subject[] { null };
1329                    try {
1330                        listenerIDs = connection.addNotificationListeners(
1331                                names, filters, subjects);
1332
1333                    } catch (IOException ioe) {
1334                        communicatorAdmin.gotIOException(ioe);
1335
1336                        listenerIDs = connection.addNotificationListeners(
1337                                names, filters, subjects);
1338                    }
1339                    return listenerIDs[0];
1340                }
1341
1342                protected void removeListenerForMBeanRemovedNotif(Integer id)
1343                        throws IOException, InstanceNotFoundException,
1344                        ListenerNotFoundException {
1345                    try {
1346                        connection.removeNotificationListeners(
1347                                MBeanServerDelegate.DELEGATE_NAME,
1348                                new Integer[] { id }, null);
1349                    } catch (IOException ioe) {
1350                        communicatorAdmin.gotIOException(ioe);
1351
1352                        connection.removeNotificationListeners(
1353                                MBeanServerDelegate.DELEGATE_NAME,
1354                                new Integer[] { id }, null);
1355                    }
1356
1357                }
1358
1359                protected void lostNotifs(String message, long number) {
1360                    final String notifType = JMXConnectionNotification.NOTIFS_LOST;
1361
1362                    final JMXConnectionNotification n = new JMXConnectionNotification(
1363                            notifType, RMIConnector.this , connectionId,
1364                            clientNotifCounter++, message, new Long(number));
1365                    sendNotification(n);
1366                }
1367            }
1368
1369            private class RMIClientCommunicatorAdmin extends
1370                    ClientCommunicatorAdmin {
1371                public RMIClientCommunicatorAdmin(long period) {
1372                    super (period);
1373                }
1374
1375                public void gotIOException(IOException ioe) throws IOException {
1376                    if (ioe instanceof  NoSuchObjectException) {
1377                        // need to restart
1378                        super .gotIOException(ioe);
1379
1380                        return;
1381                    }
1382
1383                    // check if the connection is broken
1384                    try {
1385                        connection.getDefaultDomain(null);
1386                    } catch (IOException ioexc) {
1387                        boolean toClose = false;
1388
1389                        synchronized (this ) {
1390                            if (!terminated) {
1391                                terminated = true;
1392
1393                                toClose = true;
1394                            }
1395                        }
1396
1397                        if (toClose) {
1398                            // we should close the connection,
1399                            // but send a failed notif at first
1400                            final Notification failedNotif = new JMXConnectionNotification(
1401                                    JMXConnectionNotification.FAILED, this ,
1402                                    connectionId, clientNotifSeqNo++,
1403                                    "Failed to communicate with the server: "
1404                                            + ioe.toString(), ioe);
1405
1406                            sendNotification(failedNotif);
1407
1408                            try {
1409                                close(true);
1410                            } catch (Exception e) {
1411                                // OK.
1412                                // We are closing
1413                            }
1414                        }
1415                    }
1416
1417                    // forward the exception
1418                    if (ioe instanceof  ServerException) {
1419                        /* Need to unwrap the exception.
1420                           Some user-thrown exception at server side will be wrapped by
1421                           rmi into a ServerException.
1422                           For example, a RMIConnnectorServer will wrap a
1423                           ClassNotFoundException into a UnmarshalException, and rmi
1424                           will throw a ServerException at client side which wraps this
1425                           UnmarshalException.
1426                           No failed notif here.
1427                         */
1428                        Throwable tt = ((ServerException) ioe).detail;
1429
1430                        if (tt instanceof  IOException) {
1431                            throw (IOException) tt;
1432                        } else if (tt instanceof  RuntimeException) {
1433                            throw (RuntimeException) tt;
1434                        }
1435                    }
1436
1437                    throw ioe;
1438                }
1439
1440                public void reconnectNotificationListeners(
1441                        ClientListenerInfo[] old) throws IOException {
1442                    final int len = old.length;
1443                    int i;
1444
1445                    ClientListenerInfo[] clis = new ClientListenerInfo[len];
1446
1447                    final Subject[] subjects = new Subject[len];
1448                    final ObjectName[] names = new ObjectName[len];
1449                    final NotificationListener[] listeners = new NotificationListener[len];
1450                    final NotificationFilter[] filters = new NotificationFilter[len];
1451                    final MarshalledObject[] mFilters = new MarshalledObject[len];
1452                    final Object[] handbacks = new Object[len];
1453
1454                    for (i = 0; i < len; i++) {
1455                        subjects[i] = old[i].getDelegationSubject();
1456                        names[i] = old[i].getObjectName();
1457                        listeners[i] = old[i].getListener();
1458                        filters[i] = old[i].getNotificationFilter();
1459                        mFilters[i] = new MarshalledObject<NotificationFilter>(
1460                                filters[i]);
1461                        handbacks[i] = old[i].getHandback();
1462                    }
1463
1464                    try {
1465                        Integer[] ids = addListenersWithSubjects(names,
1466                                mFilters, subjects, false);
1467
1468                        for (i = 0; i < len; i++) {
1469                            clis[i] = new ClientListenerInfo(ids[i], names[i],
1470                                    listeners[i], filters[i], handbacks[i],
1471                                    subjects[i]);
1472                        }
1473
1474                        rmiNotifClient.postReconnection(clis);
1475
1476                        return;
1477                    } catch (InstanceNotFoundException infe) {
1478                        // OK, we will do one by one
1479                    }
1480
1481                    int j = 0;
1482                    for (i = 0; i < len; i++) {
1483                        try {
1484                            Integer id = addListenerWithSubject(names[i],
1485                                    new MarshalledObject<NotificationFilter>(
1486                                            filters[i]), subjects[i], false);
1487
1488                            clis[j++] = new ClientListenerInfo(id, names[i],
1489                                    listeners[i], filters[i], handbacks[i],
1490                                    subjects[i]);
1491                        } catch (InstanceNotFoundException infe) {
1492                            logger.warning("reconnectNotificationListeners",
1493                                    "Can't reconnect listener for " + names[i]);
1494                        }
1495                    }
1496
1497                    if (j != len) {
1498                        ClientListenerInfo[] tmp = clis;
1499                        clis = new ClientListenerInfo[j];
1500                        System.arraycopy(tmp, 0, clis, 0, j);
1501                    }
1502
1503                    rmiNotifClient.postReconnection(clis);
1504                }
1505
1506                protected void checkConnection() throws IOException {
1507                    if (logger.debugOn())
1508                        logger.debug(
1509                                "RMIClientCommunicatorAdmin-checkConnection",
1510                                "Calling the method getDefaultDomain.");
1511
1512                    connection.getDefaultDomain(null);
1513                }
1514
1515                protected void doStart() throws IOException {
1516                    // Get RMIServer stub from directory or URL encoding if needed.
1517                    RMIServer stub = null;
1518                    try {
1519                        stub = (rmiServer != null) ? rmiServer : findRMIServer(
1520                                jmxServiceURL, env);
1521                    } catch (NamingException ne) {
1522                        throw new IOException("Failed to get a RMI stub: " + ne);
1523                    }
1524
1525                    // Connect IIOP Stub if needed.
1526                    stub = connectStub(stub, env);
1527
1528                    // Calling newClient on the RMIServer stub.
1529                    Object credentials = env.get(CREDENTIALS);
1530                    connection = stub.newClient(credentials);
1531
1532                    // notif issues
1533                    final ClientListenerInfo[] old = rmiNotifClient
1534                            .preReconnection();
1535
1536                    reconnectNotificationListeners(old);
1537
1538                    connectionId = getConnectionId();
1539
1540                    Notification reconnectedNotif = new JMXConnectionNotification(
1541                            JMXConnectionNotification.OPENED, this ,
1542                            connectionId, clientNotifSeqNo++,
1543                            "Reconnected to server", null);
1544                    sendNotification(reconnectedNotif);
1545
1546                }
1547
1548                protected void doStop() {
1549                    try {
1550                        close();
1551                    } catch (IOException ioe) {
1552                        logger.warning("RMIClientCommunicatorAdmin-doStop",
1553                                "Failed to call the method close():" + ioe);
1554                        logger.debug("RMIClientCommunicatorAdmin-doStop", ioe);
1555                    }
1556                }
1557            }
1558
1559            //--------------------------------------------------------------------
1560            // Private stuff - Serialization
1561            //--------------------------------------------------------------------
1562            /**
1563             * <p>In order to be usable, an IIOP stub must be connected to an ORB.
1564             * The stub is automatically connected to the ORB if:
1565             * <ul>
1566             *     <li> It was returned by the COS naming</li>
1567             *     <li> Its server counterpart has been registered in COS naming
1568             *          through JNDI.</li>
1569             * </ul>
1570             * Otherwise, it is not connected. A stub which is deserialized
1571             * from Jini is not connected. A stub which is obtained from a
1572             * non registered RMIIIOPServerImpl is not a connected.<br>
1573             * A stub which is not connected can't be serialized, and thus
1574             * can't be registered in Jini. A stub which is not connected can't
1575             * be used to invoke methods on the server.
1576             * <p>
1577             * In order to palliate this, this method will connect the
1578             * given stub if it is not yet connected. If the given
1579             * <var>RMIServer</var> is not an instance of
1580             * {@link javax.rmi.CORBA.Stub javax.rmi.CORBA.Stub}, then the
1581             * method do nothing and simply returns that stub. Otherwise,
1582             * this method will attempt to connect the stub to an ORB as
1583             * follows:
1584             * <ul>
1585             * <p>This method looks in the provided <var>environment</var> for
1586             * the "java.naming.corba.orb" property. If it is found, the
1587             * referenced object (an {@link org.omg.CORBA.ORB ORB}) is used to
1588             * connect the stub. Otherwise, a new org.omg.CORBA.ORB is created
1589             * by calling {@link
1590             * org.omg.CORBA.ORB#init(String[], Properties)
1591             * org.omg.CORBA.ORB.init((String[])null,(Properties)null)}
1592             * <p>The new created ORB is kept in a static
1593             * {@link WeakReference} and can be reused for connecting other
1594             * stubs. However, no reference is ever kept on the ORB provided
1595             * in the <var>environment</var> map, if any.
1596             * </ul>
1597             * @param rmiServer A RMI Server Stub.
1598             * @param environment An environment map, possibly containing an ORB.
1599             * @return the given stub.
1600             * @exception IllegalArgumentException if the
1601             *      <tt>java.naming.corba.orb</tt> property is specified and
1602             *      does not point to an {@link org.omg.CORBA.ORB ORB}.
1603             * @exception IOException if the connection to the ORB failed.
1604             **/
1605            static RMIServer connectStub(RMIServer rmiServer, Map environment)
1606                    throws IOException {
1607                if (rmiServer instanceof  javax.rmi.CORBA.Stub) {
1608                    javax.rmi.CORBA.Stub stub = (javax.rmi.CORBA.Stub) rmiServer;
1609                    try {
1610                        stub._orb();
1611                    } catch (BAD_OPERATION x) {
1612                        stub.connect(resolveOrb(environment));
1613                    }
1614                }
1615                return rmiServer;
1616            }
1617
1618            /**
1619             * Get the ORB specified by <var>environment</var>, or create a
1620             * new one.
1621             * <p>This method looks in the provided <var>environment</var> for
1622             * the "java.naming.corba.orb" property. If it is found, the
1623             * referenced object (an {@link org.omg.CORBA.ORB ORB}) is
1624             * returned. Otherwise, a new org.omg.CORBA.ORB is created
1625             * by calling {@link
1626             * org.omg.CORBA.ORB#init(String[], java.util.Properties)
1627             * org.omg.CORBA.ORB.init((String[])null,(Properties)null)}
1628             * <p>The new created ORB is kept in a static
1629             * {@link WeakReference} and can be reused for connecting other
1630             * stubs. However, no reference is ever kept on the ORB provided
1631             * in the <var>environment</var> map, if any.
1632             * @param environment An environment map, possibly containing an ORB.
1633             * @return An ORB.
1634             * @exception IllegalArgumentException if the
1635             *      <tt>java.naming.corba.orb</tt> property is specified and
1636             *      does not point to an {@link org.omg.CORBA.ORB ORB}.
1637             * @exception IOException if the ORB initialization failed.
1638             **/
1639            static ORB resolveOrb(Map environment) throws IOException {
1640                if (environment != null) {
1641                    final Object orb = environment.get(EnvHelp.DEFAULT_ORB);
1642                    if (orb != null && !(orb instanceof  ORB))
1643                        throw new IllegalArgumentException(EnvHelp.DEFAULT_ORB
1644                                + " must be an instance of org.omg.CORBA.ORB.");
1645                    if (orb != null)
1646                        return (ORB) orb;
1647                }
1648                final ORB orb = (RMIConnector.orb == null) ? null
1649                        : RMIConnector.orb.get();
1650                if (orb != null)
1651                    return orb;
1652
1653                final ORB newOrb = ORB.init((String[]) null, (Properties) null);
1654                RMIConnector.orb = new WeakReference<ORB>(newOrb);
1655                return newOrb;
1656            }
1657
1658            /**
1659             * Read RMIConnector fields from an {@link java.io.ObjectInputStream
1660             * ObjectInputStream}.
1661             * Calls <code>s.defaultReadObject()</code> and then initializes
1662             * all transient variables that need initializing.
1663             * @param s The ObjectInputStream to read from.
1664             * @exception InvalidObjectException if none of <var>rmiServer</var> stub
1665             *    or <var>jmxServiceURL</var> are set.
1666             * @see #RMIConnector(JMXServiceURL,Map)
1667             * @see #RMIConnector(RMIServer,Map)
1668             **/
1669            private void readObject(java.io.ObjectInputStream s)
1670                    throws IOException, ClassNotFoundException {
1671                s.defaultReadObject();
1672
1673                if (rmiServer == null && jmxServiceURL == null)
1674                    throw new InvalidObjectException(
1675                            "rmiServer and jmxServiceURL both null");
1676
1677                initTransients();
1678            }
1679
1680            /**
1681             * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream
1682             * ObjectOutputStream}.
1683             * <p>Connects the underlying RMIServer stub to an ORB, if needed,
1684             * before serializing it. This is done using the environment
1685             * map that was provided to the constructor, if any, and as documented
1686             * in {@link javax.management.remote.rmi}.</p>
1687             * <p>This method then calls <code>s.defaultWriteObject()</code>.
1688             * Usually, <var>rmiServer</var> is null if this object
1689             * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var>
1690             * is null if this object is constructed with a RMIServer stub.
1691             * <p>Note that the environment Map is not serialized, since the objects
1692             * it contains are assumed to be contextual and relevant only
1693             * with respect to the local environment (class loader, ORB, etc...).</p>
1694             * <p>After an RMIConnector is deserialized, it is assumed that the
1695             * user will call {@link #connect(Map)}, providing a new Map that
1696             * can contain values which are contextually relevant to the new
1697             * local environment.</p>
1698             * <p>Since connection to the ORB is needed prior to serializing, and
1699             * since the ORB to connect to is one of those contextual parameters,
1700             * it is not recommended to re-serialize a just de-serialized object -
1701             * as the de-serialized object has no map. Thus, when an RMIConnector
1702             * object is needed for serialization or transmission to a remote
1703             * application, it is recommended to obtain a new RMIConnector stub
1704             * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p>
1705             * @param s The ObjectOutputStream to write to.
1706             * @exception InvalidObjectException if none of <var>rmiServer</var> stub
1707             *    or <var>jmxServiceURL</var> are set.
1708             * @see #RMIConnector(JMXServiceURL,Map)
1709             * @see #RMIConnector(RMIServer,Map)
1710             **/
1711            private void writeObject(java.io.ObjectOutputStream s)
1712                    throws IOException {
1713                if (rmiServer == null && jmxServiceURL == null)
1714                    throw new InvalidObjectException(
1715                            "rmiServer and jmxServiceURL both null.");
1716                connectStub(this .rmiServer, env);
1717                s.defaultWriteObject();
1718            }
1719
1720            // Initialization of transient variables.
1721            private void initTransients() {
1722                rmbscMap = new WeakHashMap<Subject, MBeanServerConnection>();
1723                connected = false;
1724                terminated = false;
1725
1726                connectionBroadcaster = new NotificationBroadcasterSupport();
1727            }
1728
1729            //--------------------------------------------------------------------
1730            // Private stuff - Check if stub can be trusted.
1731            //--------------------------------------------------------------------
1732
1733            private static void checkStub(Remote stub, Class<?> stubClass) {
1734
1735                // Check remote stub is from the expected class.
1736                //
1737                if (stub.getClass() != stubClass) {
1738                    if (!Proxy.isProxyClass(stub.getClass())) {
1739                        throw new SecurityException("Expecting a "
1740                                + stubClass.getName() + " stub!");
1741                    } else {
1742                        InvocationHandler handler = Proxy
1743                                .getInvocationHandler(stub);
1744                        if (handler.getClass() != RemoteObjectInvocationHandler.class)
1745                            throw new SecurityException(
1746                                    "Expecting a dynamic proxy instance with a "
1747                                            + RemoteObjectInvocationHandler.class
1748                                                    .getName()
1749                                            + " invocation handler!");
1750                        else
1751                            stub = (Remote) handler;
1752                    }
1753                }
1754
1755                // Check RemoteRef in stub is from the expected class
1756                // "sun.rmi.server.UnicastRef2".
1757                //
1758                RemoteRef ref = ((RemoteObject) stub).getRef();
1759                if (ref.getClass() != UnicastRef2.class)
1760                    throw new SecurityException("Expecting a "
1761                            + UnicastRef2.class.getName()
1762                            + " remote reference in stub!");
1763
1764                // Check RMIClientSocketFactory in stub is from the expected class
1765                // "javax.rmi.ssl.SslRMIClientSocketFactory".
1766                //
1767                LiveRef liveRef = ((UnicastRef2) ref).getLiveRef();
1768                RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
1769                if (csf == null
1770                        || csf.getClass() != SslRMIClientSocketFactory.class)
1771                    throw new SecurityException("Expecting a "
1772                            + SslRMIClientSocketFactory.class.getName()
1773                            + " RMI client socket factory in stub!");
1774            }
1775
1776            //--------------------------------------------------------------------
1777            // Private stuff - RMIServer creation
1778            //--------------------------------------------------------------------
1779
1780            private RMIServer findRMIServer(JMXServiceURL directoryURL,
1781                    Map<String, Object> environment) throws NamingException,
1782                    IOException {
1783                final boolean isIiop = RMIConnectorServer.isIiopURL(
1784                        directoryURL, true);
1785                if (isIiop) {
1786                    // Make sure java.naming.corba.orb is in the Map.
1787                    environment.put(EnvHelp.DEFAULT_ORB,
1788                            resolveOrb(environment));
1789                }
1790
1791                String path = directoryURL.getURLPath();
1792                int end = path.indexOf(';');
1793                if (end < 0)
1794                    end = path.length();
1795                if (path.startsWith("/jndi/"))
1796                    return findRMIServerJNDI(path.substring(6, end),
1797                            environment, isIiop);
1798                else if (path.startsWith("/stub/"))
1799                    return findRMIServerJRMP(path.substring(6, end),
1800                            environment, isIiop);
1801                else if (path.startsWith("/ior/"))
1802                    return findRMIServerIIOP(path.substring(5, end),
1803                            environment, isIiop);
1804                else {
1805                    final String msg = "URL path must begin with /jndi/ or /stub/ "
1806                            + "or /ior/: " + path;
1807                    throw new MalformedURLException(msg);
1808                }
1809            }
1810
1811            /**
1812             * Lookup the RMIServer stub in a directory.
1813             * @param jndiURL A JNDI URL indicating the location of the Stub
1814             *                (see {@link javax.management.remote.rmi}), e.g.:
1815             *   <ul><li><tt>rmi://registry-host:port/rmi-stub-name</tt></li>
1816             *       <li>or <tt>iiop://cosnaming-host:port/iiop-stub-name</tt></li>
1817             *       <li>or <tt>ldap://ldap-host:port/java-container-dn</tt></li>
1818             *   </ul>
1819             * @param env the environment Map passed to the connector.
1820             * @param isIiop true if the stub is expected to be an IIOP stub.
1821             * @return The retrieved RMIServer stub.
1822             * @exception NamingException if the stub couldn't be found.
1823             **/
1824            private RMIServer findRMIServerJNDI(String jndiURL,
1825                    Map<String, ?> env, boolean isIiop) throws NamingException {
1826
1827                InitialContext ctx = new InitialContext(EnvHelp
1828                        .mapToHashtable(env));
1829
1830                Object objref = ctx.lookup(jndiURL);
1831                ctx.close();
1832
1833                if (isIiop)
1834                    return narrowIIOPServer(objref);
1835                else
1836                    return narrowJRMPServer(objref);
1837            }
1838
1839            private static RMIServer narrowJRMPServer(Object objref) {
1840
1841                return (RMIServer) objref;
1842            }
1843
1844            private static RMIServer narrowIIOPServer(Object objref) {
1845                try {
1846                    return (RMIServer) PortableRemoteObject.narrow(objref,
1847                            RMIServer.class);
1848                } catch (ClassCastException e) {
1849                    if (logger.traceOn())
1850                        logger.trace("narrowIIOPServer",
1851                                "Failed to narrow objref=" + objref + ": " + e);
1852                    if (logger.debugOn())
1853                        logger.debug("narrowIIOPServer", e);
1854                    return null;
1855                }
1856            }
1857
1858            private RMIServer findRMIServerIIOP(String ior, Map env,
1859                    boolean isIiop) {
1860                // could forbid "rmi:" URL here -- but do we need to?
1861                final ORB orb = (ORB) env.get(EnvHelp.DEFAULT_ORB);
1862                final Object stub = orb.string_to_object(ior);
1863                return (RMIServer) PortableRemoteObject.narrow(stub,
1864                        RMIServer.class);
1865            }
1866
1867            private RMIServer findRMIServerJRMP(String base64, Map env,
1868                    boolean isIiop) throws IOException {
1869                // could forbid "iiop:" URL here -- but do we need to?
1870                final byte[] serialized;
1871                try {
1872                    serialized = base64ToByteArray(base64);
1873                } catch (IllegalArgumentException e) {
1874                    throw new MalformedURLException("Bad BASE64 encoding: "
1875                            + e.getMessage());
1876                }
1877                final ByteArrayInputStream bin = new ByteArrayInputStream(
1878                        serialized);
1879
1880                final ClassLoader loader = EnvHelp
1881                        .resolveClientClassLoader(env);
1882                final ObjectInputStream oin = (loader == null) ? new ObjectInputStream(
1883                        bin)
1884                        : new ObjectInputStreamWithLoader(bin, loader);
1885                final Object stub;
1886                try {
1887                    stub = oin.readObject();
1888                } catch (ClassNotFoundException e) {
1889                    throw new MalformedURLException("Class not found: " + e);
1890                }
1891                return (RMIServer) PortableRemoteObject.narrow(stub,
1892                        RMIServer.class);
1893            }
1894
1895            private static final class ObjectInputStreamWithLoader extends
1896                    ObjectInputStream {
1897                ObjectInputStreamWithLoader(InputStream in, ClassLoader cl)
1898                        throws IOException {
1899                    super (in);
1900                    this .loader = cl;
1901                }
1902
1903                protected Class resolveClass(ObjectStreamClass classDesc)
1904                        throws IOException, ClassNotFoundException {
1905                    return Class.forName(classDesc.getName(), false, loader);
1906                }
1907
1908                private final ClassLoader loader;
1909            }
1910
1911            /*
1912               The following section of code avoids a class loading problem
1913               with RMI.  The problem is that an RMI stub, when deserializing
1914               a remote method return value or exception, will first of all
1915               consult the first non-bootstrap class loader it finds in the
1916               call stack.  This can lead to behavior that is not portable
1917               between implementations of the JMX Remote API.  Notably, an
1918               implementation on J2SE 1.4 will find the RMI stub's loader on
1919               the stack.  But in J2SE 5, this stub is loaded by the
1920               bootstrap loader, so RMI will find the loader of the user code
1921               that called an MBeanServerConnection method.
1922
1923               To avoid this problem, we take advantage of what the RMI stub
1924               is doing internally.  Each remote call will end up calling
1925               ref.invoke(...), where ref is the RemoteRef parameter given to
1926               the RMI stub's constructor.  It is within this call that the
1927               deserialization will happen.  So we fabricate our own RemoteRef
1928               that delegates everything to the "real" one but that is loaded
1929               by a class loader that knows no other classes.  The class
1930               loader NoCallStackClassLoader does this: the RemoteRef is an
1931               instance of the class named by proxyRefClassName, which is
1932               fabricated by the class loader using byte code that is defined
1933               by the string below.
1934
1935               The call stack when the deserialization happens is thus this:
1936               MBeanServerConnection.getAttribute (or whatever)
1937               -> RMIConnectionImpl_Stub.getAttribute
1938                  -> ProxyRef.invoke(...getAttribute...)
1939                     -> UnicastRef.invoke(...getAttribute...)
1940                        -> internal RMI stuff
1941
1942               Here UnicastRef is the RemoteRef created when the stub was
1943               deserialized (which is of some RMI internal class).  It and the
1944               "internal RMI stuff" are loaded by the bootstrap loader, so are
1945               transparent to the stack search.  The first non-bootstrap
1946               loader found is our ProxyRefLoader, as required.
1947
1948               In a future version of this code as integrated into J2SE 5,
1949               this workaround could be replaced by direct access to the
1950               internals of RMI.  For now, we use the same code base for J2SE
1951               and for the standalone Reference Implementation.
1952
1953               The byte code below encodes the following class, compiled using
1954               J2SE 1.4.2 with the -g:none option.
1955
1956            package com.sun.jmx.remote.internal;
1957
1958            import java.lang.reflect.Method;
1959            import java.rmi.Remote;
1960            import java.rmi.server.RemoteRef;
1961            import com.sun.jmx.remote.internal.ProxyRef;
1962
1963            public class PRef extends ProxyRef {
1964                public PRef(RemoteRef ref) {
1965            	super(ref);
1966                }
1967
1968                public Object invoke(Remote obj, Method method,
1969            			 Object[] params, long opnum)
1970            	    throws Exception {
1971            	return ref.invoke(obj, method, params, opnum);
1972                }
1973            }
1974             */
1975
1976            private static final String rmiServerImplStubClassName = RMIServer.class
1977                    .getName()
1978                    + "Impl_Stub";
1979            private static final Class rmiServerImplStubClass;
1980            private static final String rmiConnectionImplStubClassName = RMIConnection.class
1981                    .getName()
1982                    + "Impl_Stub";
1983            private static final Class<?> rmiConnectionImplStubClass;
1984            private static final String pRefClassName = "com.sun.jmx.remote.internal.PRef";
1985            private static final Constructor proxyRefConstructor;
1986            static {
1987                final String pRefByteCodeString = "\312\376\272\276\0\0\0.\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17\0"
1988                        + "\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/RemoteRef;"
1989                        + ")V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/reflec"
1990                        + "t/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12Exception"
1991                        + "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/"
1992                        + "sun/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/internal/Pr"
1993                        + "oxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rmi/serve"
1994                        + "r/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5\0\0\0\0"
1995                        + "\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"
1996                        + "\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"
1997                        + "\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";
1998                final byte[] pRefByteCode = NoCallStackClassLoader
1999                        .stringToBytes(pRefByteCodeString);
2000                PrivilegedExceptionAction<Constructor<?>> action = new PrivilegedExceptionAction<Constructor<?>>() {
2001                    public Constructor<?> run() throws Exception {
2002                        Class this Class = RMIConnector.class;
2003                        ClassLoader this Loader = this Class.getClassLoader();
2004                        ProtectionDomain this ProtectionDomain = this Class
2005                                .getProtectionDomain();
2006                        String[] otherClassNames = { ProxyRef.class.getName() };
2007                        ClassLoader cl = new NoCallStackClassLoader(
2008                                pRefClassName, pRefByteCode, otherClassNames,
2009                                this Loader, this ProtectionDomain);
2010                        Class<?> c = cl.loadClass(pRefClassName);
2011                        return c.getConstructor(RemoteRef.class);
2012                    }
2013                };
2014
2015                Class serverStubClass;
2016                try {
2017                    serverStubClass = Class.forName(rmiServerImplStubClassName);
2018                } catch (Exception e) {
2019                    logger.error("<clinit>", "Failed to instantiate "
2020                            + rmiServerImplStubClassName + ": " + e);
2021                    logger.debug("<clinit>", e);
2022                    serverStubClass = null;
2023                }
2024                rmiServerImplStubClass = serverStubClass;
2025
2026                Class<?> stubClass;
2027                Constructor constr;
2028                try {
2029                    stubClass = Class.forName(rmiConnectionImplStubClassName);
2030                    constr = (Constructor) AccessController
2031                            .doPrivileged(action);
2032                } catch (Exception e) {
2033                    logger.error("<clinit>",
2034                            "Failed to initialize proxy reference constructor "
2035                                    + "for " + rmiConnectionImplStubClassName
2036                                    + ": " + e);
2037                    logger.debug("<clinit>", e);
2038                    stubClass = null;
2039                    constr = null;
2040                }
2041                rmiConnectionImplStubClass = stubClass;
2042                proxyRefConstructor = constr;
2043            }
2044
2045            private static RMIConnection shadowJrmpStub(RemoteObject stub)
2046                    throws InstantiationException, IllegalAccessException,
2047                    InvocationTargetException, ClassNotFoundException,
2048                    NoSuchMethodException {
2049                RemoteRef ref = stub.getRef();
2050                RemoteRef proxyRef = (RemoteRef) proxyRefConstructor
2051                        .newInstance(new Object[] { ref });
2052                final Class[] constrTypes = { RemoteRef.class };
2053                final Constructor rmiConnectionImplStubConstructor = rmiConnectionImplStubClass
2054                        .getConstructor(constrTypes);
2055                Object[] args = { proxyRef };
2056                RMIConnection proxyStub = (RMIConnection) rmiConnectionImplStubConstructor
2057                        .newInstance(args);
2058                return proxyStub;
2059            }
2060
2061            /*
2062               The following code performs a similar trick for RMI/IIOP to the
2063               one described above for RMI/JRMP.  Unlike JRMP, though, we
2064               can't easily insert an object between the RMIConnection stub
2065               and the RMI/IIOP deserialization code, as explained below.
2066
2067               A method in an RMI/IIOP stub does the following.  It makes an
2068               org.omg.CORBA_2_3.portable.OutputStream for each request, and
2069               writes the parameters to it.  Then it calls
2070               _invoke(OutputStream) which it inherits from CORBA's
2071               ObjectImpl.  That returns an
2072               org.omg.CORBA_2_3.portable.InputStream.  The return value is
2073               read from this InputStream.  So the stack during
2074               deserialization looks like this:
2075
2076               MBeanServerConnection.getAttribute (or whatever)
2077               -> _RMIConnection_Stub.getAttribute
2078                  -> Util.readAny (a CORBA method)
2079                     -> InputStream.read_any
2080                        -> internal CORBA stuff
2081
2082               What we would have *liked* to have done would be the same thing
2083               as for RMI/JRMP.  We create a "ProxyDelegate" that is an
2084               org.omg.CORBA.portable.Delegate that simply forwards every
2085               operation to the real original Delegate from the RMIConnection
2086               stub, except that the InputStream returned by _invoke is
2087               wrapped by a "ProxyInputStream" that is loaded by our
2088               NoCallStackClassLoader.
2089
2090               Unfortunately, this doesn't work, at least with Sun's J2SE
2091               1.4.2, because the CORBA code is not designed to allow you to
2092               change Delegates arbitrarily.  You get a ClassCastException
2093               from code that expects the Delegate to implement an internal
2094               interface.
2095
2096               So instead we do the following.  We create a subclass of the
2097               stub that overrides the _invoke method so as to wrap the
2098               returned InputStream in a ProxyInputStream.  We create a
2099               subclass of ProxyInputStream using the NoCallStackClassLoader
2100               and override its read_any and read_value(Class) methods.
2101               (These are the only methods called during deserialization of
2102               MBeanServerConnection return values.)  We extract the Delegate
2103               from the original stub and insert it into our subclass stub,
2104               and away we go.  The state of a stub consists solely of its
2105               Delegate.
2106
2107               We also need to catch ApplicationException, which will encode
2108               any exceptions declared in the throws clause of the called
2109               method.  Its InputStream needs to be wrapped in a
2110               ProxyInputSteam too.
2111
2112               We override _releaseReply in the stub subclass so that it
2113               replaces a ProxyInputStream argument with the original
2114               InputStream.  This avoids problems if the implementation of
2115               _releaseReply ends up casting this InputStream to an
2116               implementation-specific interface (which in Sun's J2SE 5 it
2117               does).
2118
2119               It is not strictly necessary for the stub subclass to be loaded
2120               by a NoCallStackClassLoader, since the call-stack search stops
2121               at the ProxyInputStream subclass.  However, it is convenient
2122               for two reasons.  One is that it means that the
2123               ProxyInputStream subclass can be accessed directly, without
2124               using reflection.  The other is that it avoids build problems,
2125               since usually stubs are created after other classes are
2126               compiled, so we can't access them from this class without,
2127               again, using reflection.
2128
2129               The strings below encode the following two Java classes,
2130               compiled using J2SE 1.4.2 with javac -g:none.
2131
2132            package com.sun.jmx.remote.internal;
2133
2134            import org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub;
2135
2136            import org.omg.CORBA.portable.ApplicationException;
2137            import org.omg.CORBA.portable.InputStream;
2138            import org.omg.CORBA.portable.OutputStream;
2139            import org.omg.CORBA.portable.RemarshalException;
2140
2141            public class ProxyStub extends _RMIConnection_Stub {
2142                public InputStream _invoke(OutputStream out)
2143            	    throws ApplicationException, RemarshalException {
2144            	    	try {
2145            	    return new PInputStream(super._invoke(out));
2146            	    	} catch (ApplicationException e) {
2147            	    	    InputStream pis = new PInputStream(e.getInputStream());
2148            	    	    throw new ApplicationException(e.getId(), pis);
2149            	    	}
2150                }
2151
2152                public void _releaseReply(InputStream in) {
2153            	PInputStream pis = (PInputStream) in;
2154            	super._releaseReply(pis.getProxiedInputStream());
2155                }
2156            }
2157
2158            package com.sun.jmx.remote.internal;
2159
2160            public class PInputStream extends ProxyInputStream {
2161                public PInputStream(org.omg.CORBA.portable.InputStream in) {
2162            	super(in);
2163                }
2164
2165                public org.omg.CORBA.Any read_any() {
2166            	return in.read_any();
2167                }
2168
2169                public java.io.Serializable read_value(Class clz) {
2170            	return narrow().read_value(clz);
2171                }
2172            }
2173
2174
2175             */
2176            private static final String iiopConnectionStubClassName = "org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub";
2177            private static final String proxyStubClassName = "com.sun.jmx.remote.internal.ProxyStub";
2178            private static final String pInputStreamClassName = "com.sun.jmx.remote.internal.PInputStream";
2179            private static final Class proxyStubClass;
2180            static {
2181                final String proxyStubByteCodeString = "\312\376\272\276\0\0\0.\0)\12\0\14\0\26\7\0\27\12\0\14\0\30\12"
2182                        + "\0\2\0\31\7\0\32\12\0\5\0\33\12\0\5\0\34\12\0\5\0\35\12\0\2\0"
2183                        + "\36\12\0\14\0\37\7\0\40\7\0!\1\0\6<init>\1\0\3()V\1\0\4Code\1"
2184                        + "\0\7_invoke\1\0K(Lorg/omg/CORBA/portable/OutputStream;)Lorg/o"
2185                        + "mg/CORBA/portable/InputStream;\1\0\12Exceptions\7\0\"\1\0\15_"
2186                        + "releaseReply\1\0'(Lorg/omg/CORBA/portable/InputStream;)V\14\0"
2187                        + "\15\0\16\1\0(com/sun/jmx/remote/internal/PInputStream\14\0\20"
2188                        + "\0\21\14\0\15\0\25\1\0+org/omg/CORBA/portable/ApplicationExce"
2189                        + "ption\14\0#\0$\14\0%\0&\14\0\15\0'\14\0(\0$\14\0\24\0\25\1\0%"
2190                        + "com/sun/jmx/remote/internal/ProxyStub\1\0<org/omg/stub/javax/"
2191                        + "management/remote/rmi/_RMIConnection_Stub\1\0)org/omg/CORBA/p"
2192                        + "ortable/RemarshalException\1\0\16getInputStream\1\0&()Lorg/om"
2193                        + "g/CORBA/portable/InputStream;\1\0\5getId\1\0\24()Ljava/lang/S"
2194                        + "tring;\1\09(Ljava/lang/String;Lorg/omg/CORBA/portable/InputSt"
2195                        + "ream;)V\1\0\25getProxiedInputStream\0!\0\13\0\14\0\0\0\0\0\3\0"
2196                        + "\1\0\15\0\16\0\1\0\17\0\0\0\21\0\1\0\1\0\0\0\5*\267\0\1\261\0"
2197                        + "\0\0\0\0\1\0\20\0\21\0\2\0\17\0\0\0;\0\4\0\4\0\0\0'\273\0\2Y*"
2198                        + "+\267\0\3\267\0\4\260M\273\0\2Y,\266\0\6\267\0\4N\273\0\5Y,\266"
2199                        + "\0\7-\267\0\10\277\0\1\0\0\0\14\0\15\0\5\0\0\0\22\0\0\0\6\0\2"
2200                        + "\0\5\0\23\0\1\0\24\0\25\0\1\0\17\0\0\0\36\0\2\0\2\0\0\0\22+\306"
2201                        + "\0\13+\300\0\2\266\0\11L*+\267\0\12\261\0\0\0\0\0\0";
2202                final String pInputStreamByteCodeString = "\312\376\272\276\0\0\0.\0\36\12\0\7\0\17\11\0\6\0\20\12\0\21\0"
2203                        + "\22\12\0\6\0\23\12\0\24\0\25\7\0\26\7\0\27\1\0\6<init>\1\0'(L"
2204                        + "org/omg/CORBA/portable/InputStream;)V\1\0\4Code\1\0\10read_an"
2205                        + "y\1\0\25()Lorg/omg/CORBA/Any;\1\0\12read_value\1\0)(Ljava/lan"
2206                        + "g/Class;)Ljava/io/Serializable;\14\0\10\0\11\14\0\30\0\31\7\0"
2207                        + "\32\14\0\13\0\14\14\0\33\0\34\7\0\35\14\0\15\0\16\1\0(com/sun"
2208                        + "/jmx/remote/internal/PInputStream\1\0,com/sun/jmx/remote/inte"
2209                        + "rnal/ProxyInputStream\1\0\2in\1\0$Lorg/omg/CORBA/portable/Inp"
2210                        + "utStream;\1\0\"org/omg/CORBA/portable/InputStream\1\0\6narrow"
2211                        + "\1\0*()Lorg/omg/CORBA_2_3/portable/InputStream;\1\0&org/omg/C"
2212                        + "ORBA_2_3/portable/InputStream\0!\0\6\0\7\0\0\0\0\0\3\0\1\0\10"
2213                        + "\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\0"
2214                        + "\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"
2215                        + "\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"
2216                        + "\11*\266\0\4+\266\0\5\260\0\0\0\0\0\0";
2217                final byte[] proxyStubByteCode = NoCallStackClassLoader
2218                        .stringToBytes(proxyStubByteCodeString);
2219                final byte[] pInputStreamByteCode = NoCallStackClassLoader
2220                        .stringToBytes(pInputStreamByteCodeString);
2221                final String[] classNames = { proxyStubClassName,
2222                        pInputStreamClassName };
2223                final byte[][] byteCodes = { proxyStubByteCode,
2224                        pInputStreamByteCode };
2225                final String[] otherClassNames = { iiopConnectionStubClassName,
2226                        ProxyInputStream.class.getName(), };
2227                PrivilegedExceptionAction<Class<?>> action = new PrivilegedExceptionAction<Class<?>>() {
2228                    public Class<?> run() throws Exception {
2229
2230                        Class this Class = RMIConnector.class;
2231                        ClassLoader this Loader = this Class.getClassLoader();
2232                        ProtectionDomain this ProtectionDomain = this Class
2233                                .getProtectionDomain();
2234                        ClassLoader cl = new NoCallStackClassLoader(classNames,
2235                                byteCodes, otherClassNames, this Loader,
2236                                this ProtectionDomain);
2237                        return cl.loadClass(proxyStubClassName);
2238                    }
2239                };
2240                Class<?> stubClass;
2241                try {
2242                    stubClass = AccessController.doPrivileged(action);
2243                } catch (Exception e) {
2244                    logger.error("<clinit>",
2245                            "Unexpected exception making shadow IIOP stub class: "
2246                                    + e);
2247                    logger.debug("<clinit>", e);
2248                    stubClass = null;
2249                }
2250                proxyStubClass = stubClass;
2251            }
2252
2253            private static RMIConnection shadowIiopStub(Stub stub)
2254                    throws InstantiationException, IllegalAccessException {
2255                Stub proxyStub = (Stub) proxyStubClass.newInstance();
2256                proxyStub._set_delegate(stub._get_delegate());
2257                return (RMIConnection) proxyStub;
2258            }
2259
2260            private static RMIConnection getConnection(RMIServer server,
2261                    Object credentials, boolean checkStub) throws IOException {
2262                RMIConnection c = server.newClient(credentials);
2263                if (checkStub)
2264                    checkStub(c, rmiConnectionImplStubClass);
2265                try {
2266                    if (c.getClass() == rmiConnectionImplStubClass)
2267                        return shadowJrmpStub((RemoteObject) c);
2268                    if (c.getClass().getName().equals(
2269                            iiopConnectionStubClassName))
2270                        return shadowIiopStub((Stub) c);
2271                    logger
2272                            .trace(
2273                                    "getConnection",
2274                                    "Did not wrap "
2275                                            + c.getClass()
2276                                            + " to foil "
2277                                            + "stack search for classes: class loading semantics "
2278                                            + "may be incorrect");
2279                } catch (Exception e) {
2280                    logger
2281                            .error(
2282                                    "getConnection",
2283                                    "Could not wrap "
2284                                            + c.getClass()
2285                                            + " to foil "
2286                                            + "stack search for classes: class loading semantics "
2287                                            + "may be incorrect: " + e);
2288                    logger.debug("getConnection", e);
2289                    // so just return the original stub, which will work for all
2290                    // but the most exotic class loading situations
2291                }
2292                return c;
2293            }
2294
2295            private static byte[] base64ToByteArray(String s) {
2296                int sLen = s.length();
2297                int numGroups = sLen / 4;
2298                if (4 * numGroups != sLen)
2299                    throw new IllegalArgumentException(
2300                            "String length must be a multiple of four.");
2301                int missingBytesInLastGroup = 0;
2302                int numFullGroups = numGroups;
2303                if (sLen != 0) {
2304                    if (s.charAt(sLen - 1) == '=') {
2305                        missingBytesInLastGroup++;
2306                        numFullGroups--;
2307                    }
2308                    if (s.charAt(sLen - 2) == '=')
2309                        missingBytesInLastGroup++;
2310                }
2311                byte[] result = new byte[3 * numGroups
2312                        - missingBytesInLastGroup];
2313
2314                // Translate all full groups from base64 to byte array elements
2315                int inCursor = 0, outCursor = 0;
2316                for (int i = 0; i < numFullGroups; i++) {
2317                    int ch0 = base64toInt(s.charAt(inCursor++));
2318                    int ch1 = base64toInt(s.charAt(inCursor++));
2319                    int ch2 = base64toInt(s.charAt(inCursor++));
2320                    int ch3 = base64toInt(s.charAt(inCursor++));
2321                    result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
2322                    result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
2323                    result[outCursor++] = (byte) ((ch2 << 6) | ch3);
2324                }
2325
2326                // Translate partial group, if present
2327                if (missingBytesInLastGroup != 0) {
2328                    int ch0 = base64toInt(s.charAt(inCursor++));
2329                    int ch1 = base64toInt(s.charAt(inCursor++));
2330                    result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
2331
2332                    if (missingBytesInLastGroup == 1) {
2333                        int ch2 = base64toInt(s.charAt(inCursor++));
2334                        result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
2335                    }
2336                }
2337                // assert inCursor == s.length()-missingBytesInLastGroup;
2338                // assert outCursor == result.length;
2339                return result;
2340            }
2341
2342            /**
2343             * Translates the specified character, which is assumed to be in the
2344             * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
2345             *
2346             * @throws IllegalArgumentException if
2347             *        c is not in the Base64 Alphabet.
2348             */
2349            private static int base64toInt(char c) {
2350                int result;
2351
2352                if (c >= base64ToInt.length)
2353                    result = -1;
2354                else
2355                    result = base64ToInt[c];
2356
2357                if (result < 0)
2358                    throw new IllegalArgumentException("Illegal character " + c);
2359                return result;
2360            }
2361
2362            /**
2363             * This array is a lookup table that translates unicode characters
2364             * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
2365             * into their 6-bit positive integer equivalents.  Characters that
2366             * are not in the Base64 alphabet but fall within the bounds of the
2367             * array are translated to -1.
2368             */
2369            private static final byte base64ToInt[] = { -1, -1, -1, -1, -1, -1,
2370                    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2371                    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2372                    -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
2373                    55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0,
2374                    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
2375                    18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
2376                    27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
2377                    42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
2378
2379            //--------------------------------------------------------------------
2380            // Private stuff - Find / Set default class loader
2381            //--------------------------------------------------------------------
2382            private ClassLoader pushDefaultClassLoader() {
2383                final Thread t = Thread.currentThread();
2384                final ClassLoader old = t.getContextClassLoader();
2385                if (defaultClassLoader != null)
2386                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
2387                        public Void run() {
2388                            t.setContextClassLoader(defaultClassLoader);
2389                            return null;
2390                        }
2391                    });
2392                return old;
2393            }
2394
2395            private void popDefaultClassLoader(final ClassLoader old) {
2396                AccessController.doPrivileged(new PrivilegedAction<Void>() {
2397                    public Void run() {
2398                        Thread.currentThread().setContextClassLoader(old);
2399                        return null;
2400                    }
2401                });
2402            }
2403
2404            //--------------------------------------------------------------------
2405            // Private variables
2406            //--------------------------------------------------------------------
2407            /**
2408             * @serial The RMIServer stub of the RMI JMX Connector server to
2409             * which this client connector is (or will be) connected. This
2410             * field can be null when <var>jmxServiceURL</var> is not
2411             * null. This includes the case where <var>jmxServiceURL</var>
2412             * contains a serialized RMIServer stub. If both
2413             * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
2414             * serialization will fail.
2415             *
2416             * @see #RMIConnector(RMIServer,Map)
2417             **/
2418            private final RMIServer rmiServer;
2419
2420            /**
2421             * @serial The JMXServiceURL of the RMI JMX Connector server to
2422             * which this client connector will be connected. This field can
2423             * be null when <var>rmiServer</var> is not null. If both
2424             * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
2425             * serialization will fail.
2426             *
2427             * @see #RMIConnector(JMXServiceURL,Map)
2428             **/
2429            private final JMXServiceURL jmxServiceURL;
2430
2431            // ---------------------------------------------------------
2432            // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
2433            // ---------------------------------------------------------
2434            // Any transient variable which needs to be initialized should
2435            // be initialized in the method initTransient()
2436            private transient Map<String, Object> env;
2437            private transient ClassLoader defaultClassLoader;
2438            private transient RMIConnection connection;
2439            private transient String connectionId;
2440
2441            private transient long clientNotifSeqNo = 0;
2442
2443            private transient WeakHashMap<Subject, MBeanServerConnection> rmbscMap;
2444
2445            private transient RMINotifClient rmiNotifClient;
2446            // = new RMINotifClient(new Integer(0));
2447
2448            private transient long clientNotifCounter = 0;
2449
2450            private transient boolean connected;
2451            // = false;
2452            private transient boolean terminated;
2453            // = false;
2454
2455            private transient Exception closeException;
2456
2457            private transient NotificationBroadcasterSupport connectionBroadcaster;
2458
2459            private transient ClientCommunicatorAdmin communicatorAdmin;
2460
2461            /**
2462             * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
2463             * connect unconnected stubs.
2464             **/
2465            private static WeakReference<ORB> orb = null;
2466
2467            // TRACES & DEBUG
2468            //---------------
2469            private static String objects(final Object[] objs) {
2470                if (objs == null)
2471                    return "null";
2472                else
2473                    return Arrays.asList(objs).toString();
2474            }
2475
2476            private static String strings(final String[] strs) {
2477                return objects(strs);
2478            }
2479        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.