📄 rmiconnector.java
字号:
listeners[i], filters[i], handbacks[i], subjects[i]); } catch (InstanceNotFoundException infe) { logger.warning("reconnectNotificationListeners", "Can't reconnect listener for " + names[i]); } } if (j != len) { ClientListenerInfo[] tmp = clis; clis = new ClientListenerInfo[j]; System.arraycopy(tmp, 0, clis, 0, j); } rmiNotifClient.postReconnection(clis); } protected void checkConnection() throws IOException { if (logger.debugOn()) logger.debug("RMIClientCommunicatorAdmin-checkConnection", "Calling the method getDefaultDomain."); connection.getDefaultDomain(null); } protected void doStart() throws IOException { // Get RMIServer stub from directory or URL encoding if needed. RMIServer stub = null; try { stub = (rmiServer!=null)?rmiServer: findRMIServer(jmxServiceURL, env); } catch (NamingException ne) { throw new IOException("Failed to get a RMI stub: "+ne); } // Connect IIOP Stub if needed. stub = connectStub(stub,env); // Calling newClient on the RMIServer stub. Object credentials = env.get(CREDENTIALS); connection = stub.newClient(credentials); // notif issues final ClientListenerInfo[] old = rmiNotifClient.preReconnection(); reconnectNotificationListeners(old); connectionId = getConnectionId(); Notification reconnectedNotif = new JMXConnectionNotification(JMXConnectionNotification.OPENED, this, connectionId, clientNotifID++, "Reconnected to server", null); sendNotification(reconnectedNotif); } protected void doStop() { try { close(); } catch (IOException ioe) { logger.warning("RMIClientCommunicatorAdmin-doStop", "Failed to call the method close():" + ioe); logger.debug("RMIClientCommunicatorAdmin-doStop",ioe); } } } //-------------------------------------------------------------------- // Private stuff - Serialization //-------------------------------------------------------------------- /** * <p>In order to be usable, an IIOP stub must be connected to an ORB. * The stub is automagically connected to the ORB if: * <ul> * <li> It was returned by the COS naming</li> * <li> Its server counterpart has been registered in COS naming * through JNDI.</li> * </ul> * Otherwise, it is not connected. A stub which is deserialized * from Jini is not connected. A stub which is obtained from a * non registered RMIIIOPServerImpl is not a connected.<br> * A stub which is not connected can't be serialized, and thus * can't be registered in Jini. A stub which is not connected can't * be used to invoke methods on the server. * <p> * In order to palliate this, this method will connect the * given stub if it is not yet connected. If the given * <var>RMIServer</var> is not an instance of * {@link javax.rmi.CORBA.Stub javax.rmi.CORBA.Stub}, then the * method do nothing and simply returns that stub. Otherwise, * this method will attempt to connect the stub to an ORB as * follows: * <ul> * <p>This method looks in the provided <var>environment</var> for * the "java.naming.corba.orb" property. If it is found, the * referenced object (an {@link org.omg.CORBA.ORB ORB}) is used to * connect the stub. Otherwise, a new org.omg.CORBA.ORB is created * by calling {@link * org.omg.CORBA.ORB#init(String[], Properties) * org.omg.CORBA.ORB.init((String[])null,(Properties)null)} * <p>The new created ORB is kept in a static * {@link WeakReference} and can be reused for connecting other * stubs. However, no reference is ever kept on the ORB provided * in the <var>environment</var> map, if any. * </ul> * @param rmiServer A RMI Server Stub. * @param environment An environment map, possibly containing an ORB. * @return the given stub. * @exception IllegalArgumentException if the * <tt>java.naming.corba.orb</tt> property is specified and * does not point to an {@link org.omg.CORBA.ORB ORB}. * @exception IOException if the connection to the ORB failed. **/ static RMIServer connectStub(RMIServer rmiServer, Map environment) throws IOException { if (rmiServer instanceof javax.rmi.CORBA.Stub) { javax.rmi.CORBA.Stub stub = (javax.rmi.CORBA.Stub) rmiServer; try { stub._orb(); } catch (org.omg.CORBA.BAD_OPERATION x) { stub.connect(resolveOrb(environment)); } } return rmiServer; } /** * Get the ORB specified by <var>environment</var>, or create a * new one. * <p>This method looks in the provided <var>environment</var> for * the "java.naming.corba.orb" property. If it is found, the * referenced object (an {@link org.omg.CORBA.ORB ORB}) is * returned. Otherwise, a new org.omg.CORBA.ORB is created * by calling {@link * org.omg.CORBA.ORB#init(String[], java.util.Properties) * org.omg.CORBA.ORB.init((String[])null,(Properties)null)} * <p>The new created ORB is kept in a static * {@link WeakReference} and can be reused for connecting other * stubs. However, no reference is ever kept on the ORB provided * in the <var>environment</var> map, if any. * @param environment An environment map, possibly containing an ORB. * @return An ORB. * @exception IllegalArgumentException if the * <tt>java.naming.corba.orb</tt> property is specified and * does not point to an {@link org.omg.CORBA.ORB ORB}. * @exception IOException if the ORB initialization failed. **/ static org.omg.CORBA.ORB resolveOrb(Map environment) throws IOException { if (environment != null) { final Object orb = environment.get(EnvHelp.DEFAULT_ORB); if (orb != null && !(orb instanceof org.omg.CORBA.ORB)) throw new IllegalArgumentException(EnvHelp.DEFAULT_ORB + " must be an instance of org.omg.CORBA.ORB."); if (orb != null) return (org.omg.CORBA.ORB)orb; } final Object orb = (RMIConnector.orb==null)?null:RMIConnector.orb.get(); if (orb != null) return (org.omg.CORBA.ORB)orb; final org.omg.CORBA.ORB newOrb = org.omg.CORBA.ORB.init((String[])null, (Properties)null); RMIConnector.orb = new WeakReference(newOrb); return newOrb; } /** * Read RMIConnector fields from an {@link java.io.ObjectInputStream * ObjectInputStream}. * Calls <code>s.defaultReadObject()</code> and then initializes * all transient variables that need initializing. * @param s The ObjectInputStream to read from. * @exception InvalidObjectException if none of <var>rmiServer</var> stub * or <var>jmxServiceURL</var> are set. * @see #RMIConnector(JMXServiceURL,Map) * @see #RMIConnector(RMIServer,Map) **/ private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); if (rmiServer == null && jmxServiceURL == null) throw new InvalidObjectException("rmiServer and jmxServiceURL both null"); initTransients(); } /** * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream * ObjectOutputStream}. * <p>Connects the underlying RMIServer stub to an ORB, if needed, * before serializing it. This is done using the environment * map that was provided to the constructor, if any, and as documented * in {@link javax.management.remote.rmi}.</p> * <p>This method then calls <code>s.defaultWriteObject()</code>. * Usually, <var>rmiServer</var> is null if this object * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var> * is null if this object is constructed with a RMIServer stub. * <p>Note that the environment Map is not serialized, since the objects * it contains are assumed to be contextual and relevant only * with respect to the local environment (class loader, ORB, etc...).</p> * <p>After an RMIConnector is deserialized, it is assumed that the * user will call {@link #connect(Map)}, providing a new Map that * can contain values which are contextually relevant to the new * local environment.</p> * <p>Since connection to the ORB is needed prior to serializing, and * since the ORB to connect to is one of those contextual parameters, * it is not recommended to re-serialize a just de-serialized object - * as the de-serialized object has no map. Thus, when an RMIConnector * object is needed for serialization or transmission to a remote * application, it is recommended to obtain a new RMIConnector stub * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p> * @param s The ObjectOutputStream to write to. * @exception InvalidObjectException if none of <var>rmiServer</var> stub * or <var>jmxServiceURL</var> are set. * @see #RMIConnector(JMXServiceURL,Map) * @see #RMIConnector(RMIServer,Map) **/ private void writeObject(java.io.ObjectOutputStream s) throws IOException { if (rmiServer == null && jmxServiceURL == null) throw new InvalidObjectException("rmiServer and jmxServiceURL both null."); connectStub(this.rmiServer,env); s.defaultWriteObject(); } // Initialization of transient variables. private void initTransients() { rmbscMap = new WeakHashMap(); connected = false; terminated = false; connectionBroadcaster = new NotificationBroadcasterSupport(); } //-------------------------------------------------------------------- // Private stuff - RMIServer creation //-------------------------------------------------------------------- private RMIServer findRMIServer(JMXServiceURL directoryURL, Map environment) throws NamingException, IOException { final boolean isIiop = RMIConnectorServer.isIiopURL(directoryURL,true); if (isIiop) { // Make sure java.naming.corba.orb is in the Map. environment.put(EnvHelp.DEFAULT_ORB,resolveOrb(environment)); } String path = directoryURL.getURLPath(); if (path.startsWith("/jndi/")) return findRMIServerJNDI(path.substring(6), environment, isIiop); else if (path.startsWith("/stub/")) return findRMIServerJRMP(path.substring(6), environment, isIiop); else if (path.startsWith("/ior/")) return findRMIServerIIOP(path.substring(5), environment, isIiop); else { final String msg = "URL path must begin with /jndi/ or /stub/ " + "or /ior/: " + path; throw new MalformedURLException(msg); } } /** * Lookup the RMIServer stub in a directory. * @param jndiURL A JNDI URL indicating the location of the Stub * (see {@link javax.management.remote.rmi}), e.g.: * <ul><li><tt>rmi://registry-host:port/rmi-stub-name</tt></li> * <li>or <tt>iiop://cosnaming-host:port/iiop-stub-name</tt></li> * <li>or <tt>ldap://ldap-host:port/java-container-dn</tt></li> * </ul> * @param env the environment Map passed to the connector. * @param isIiop true if the stub is expected to be an IIOP stub. * @return The retrieved RMIServer stub. * @exception NamingException if the stub couldn't be found. **/ private RMIServer findRMIServerJNDI(String jndiURL, Map env, boolean isIiop) throws NamingException { InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env)); Object objref = ctx.lookup(jndiURL); ctx.close(); if (isIiop) return narrowIIOPServer(objref); else return narrowJRMPServer(objref); } private static RMIServer narrowJRMPServer(Object objref) { return (RMIServer) objref; } private static RMIServer narrowIIOPServer(Object objref) { try { return (RMIServer) PortableRemoteObject.narrow(objref, RMIServer.class); } catch (ClassCastException e) { if (logger.traceOn()) logger.trace("narrowIIOPServer","Failed to narrow objref=" + objref + ": " + e); if (logger.debugOn()) logger.debug("narrowIIOPServer",e); return null; } } private RMIServer findRMIServerIIOP(String ior, Map env, boolean isIiop) { // could forbid "rmi:" URL here -- but do we need to? final org.omg.CORBA.ORB orb = (org.omg.CORBA.ORB) env.get(EnvHelp.DEFAULT_ORB); final Object stub = orb.string_to_object(ior); return (RMIServer) PortableRemoteObject.narrow(stub, RMIServer.class); } private RMIServer findRMIServerJRMP(String base64, Map env, boolean isIiop) throws IOException { // could forbid "iiop:" URL here -- but do we need to? final byte[] serialized; try { serialized = base64ToByteArray(base64); } catch (IllegalArgumentException e) { throw new MalformedURLException("Bad BASE64 encoding: " + e.getMessage()); } final ByteArrayInputStream bin = new ByteArrayInputStream(serialized); final ClassLoader loader = EnvHelp.resolveClientClassLoader(env); final ObjectInputStream oin = (loader == null) ? new ObjectInputStream(bin) : new ObjectInputStreamWithLoader(bin, loader); final Object stub; try { stub = oin.readObject(); } catch (ClassNotFoundException e) { throw new MalformedURLException("Class not found: " + e); } return (RMIServer) PortableRemoteObject.narrow(stub, RMIServer.class); } private static final class ObjectInputStreamWithLoader extends ObjectInputStream { ObjectInputStreamWithLoader(InputStream in, ClassLoader cl) throws IOException { super(in); this.loader = cl; } protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { return Class.forName(classDesc.getName(), false, loader); } private final ClassLoader loader; } /* The following section of code avoids a class loading problem with RMI. The problem is that an RMI stub, when deserializing a remote method return value or exception, will first of all consult the first non-bootstrap class loader it finds in the call stack. This can lead to behavior that is not portable between implementations of the JMX Remote API. Notably, an implementation on J2SE 1.4 will find the RMI stub's loader on the stack. But in J2SE 5, this stub is loaded by the bootstrap loader, so RMI will find the loader of the user code that called an MBeanServerConnection method. To avoid this problem, we take advantage of what the RMI stub
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -