📄 rmiconnectorserver.java
字号:
// fit e in the nested exception if we are on 1.4 throw newIOException("Cannot bind to URL ["+jndiUrl+"]: " + e, e); } } else { // if jndiURL is null, we must encode the stub into the URL. if (tracing) logger.trace("start", "Encoding URL"); encodeStubInAddress(objref, attributes); if (tracing) logger.trace("start", "Encoded URL: " + this.address); } } catch (Exception e) { try { rmiServer.close(); } catch (Exception x) { // OK: we are already throwing another exception } if (e instanceof RuntimeException) throw (RuntimeException) e; else if (e instanceof IOException) throw (IOException) e; else throw newIOException("Got unexpected exception while " + "starting the connector server: " + e, e); } rmiServerImpl = rmiServer; synchronized(openedServers) { openedServers.add(this); } state = STARTED; if (tracing) { logger.trace("start", "Connector Server Address = " + address); logger.trace("start", "started."); } } /** * <p>Deactivates the connector server, that is, stops listening for * client connections. Calling this method will also close all * client connections that were made by this server. After this * method returns, whether normally or with an exception, the * connector server will not create any new client * connections.</p> * * <p>Once a connector server has been stopped, it cannot be started * again.</p> * * <p>Calling this method when the connector server has already * been stopped has no effect. Calling this method when the * connector server has not yet been started will disable the * connector server object permanently.</p> * * <p>If closing a client connection produces an exception, that * exception is not thrown from this method. A {@link * JMXConnectionNotification} is emitted from this MBean with the * connection ID of the connection that could not be closed.</p> * * <p>Closing a connector server is a potentially slow operation. * For example, if a client machine with an open connection has * crashed, the close operation might have to wait for a network * protocol timeout. Callers that do not want to block in a close * operation should do it in a separate thread.</p> * * <p>This method calls the method {@link RMIServerImpl#close() * close} on the connector server's <code>RMIServerImpl</code> * object.</p> * * <p>If the <code>RMIServerImpl</code> was bound to a JNDI * directory by the {@link #start() start} method, it is unbound * from the directory by this method.</p> * * @exception IOException if the server cannot be closed cleanly, * or if the <code>RMIServerImpl</code> cannot be unbound from the * directory. When this exception is thrown, the server has * already attempted to close all client connections, if * appropriate; to call {@link RMIServerImpl#close()}; and to * unbind the <code>RMIServerImpl</code> from its directory, if * appropriate. All client connections are closed except possibly * those that generated exceptions when the server attempted to * close them. */ public void stop() throws IOException { final boolean tracing = logger.traceOn(); synchronized (this) { if (state == STOPPED) { if (tracing) logger.trace("stop","already stopped."); return; } else if (state == CREATED) { if (tracing) logger.trace("stop","not started yet."); } if (tracing) logger.trace("stop", "stopping."); state = STOPPED; } synchronized(openedServers) { openedServers.remove(this); } IOException exception = null; // rmiServerImpl can be null if stop() called without start() if (rmiServerImpl != null) { try { if (tracing) logger.trace("stop", "closing RMI server."); rmiServerImpl.close(); } catch (IOException e) { if (tracing) logger.trace("stop", "failed to close RMI server: " + e); if (logger.debugOn()) logger.debug("stop",e); exception = e; } } if (boundJndiUrl != null) { try { if (tracing) logger.trace("stop", "unbind from external directory: " + boundJndiUrl); final Hashtable usemap = EnvHelp.mapToHashtable(attributes); InitialContext ctx = new InitialContext(usemap); ctx.unbind(boundJndiUrl); ctx.close(); } catch (NamingException e) { if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e); if (logger.debugOn()) logger.debug("stop",e); // fit e in as the nested exception if we are on 1.4 if (exception == null) exception = newIOException("Cannot bind to URL: " + e, e); } } if (exception != null) throw exception; if (tracing) logger.trace("stop", "stopped"); } public synchronized boolean isActive() { return (state == STARTED); } public JMXServiceURL getAddress() { if (!isActive()) return null; return address; } public Map<String,?> getAttributes() { Map map = EnvHelp.filterAttributes(attributes); return Collections.unmodifiableMap(map); } public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf) { super.setMBeanServerForwarder(mbsf); if (rmiServerImpl != null) rmiServerImpl.setMBeanServer(getMBeanServer()); } /* We repeat the definitions of connection{Opened,Closed,Failed} here so that they are accessible to other classes in this package even though they have protected access. */ protected void connectionOpened(String connectionId, String message, Object userData) { super.connectionOpened(connectionId, message, userData); } protected void connectionClosed(String connectionId, String message, Object userData) { super.connectionClosed(connectionId, message, userData); } protected void connectionFailed(String connectionId, String message, Object userData) { super.connectionFailed(connectionId, message, userData); } /** * Bind a stub to a registry. * @param jndiUrl URL of the stub in the registry, extracted * from the <code>JMXServiceURL</code>. * @param attributes A Hashtable containing environment parameters, * built from the Map specified at this object creation. * @param rmiServer The object to bind in the registry * @param rebind true if the object must be rebound. **/ void bind(String jndiUrl, Hashtable attributes, RMIServer rmiServer, boolean rebind) throws NamingException, MalformedURLException { // if jndiURL is not null, we nust bind the stub to a // directory. InitialContext ctx = new InitialContext(attributes); if (rebind) ctx.rebind(jndiUrl, rmiServer); else ctx.bind(jndiUrl, rmiServer); ctx.close(); } /** * Creates a new RMIServerImpl. **/ RMIServerImpl newServer() throws IOException { final boolean iiop = isIiopURL(address,true); final int port; if (address == null) port = 0; else port = address.getPort(); if (iiop) return newIIOPServer(attributes); else return newJRMPServer(attributes, port); } /** * Encode a stub into the JMXServiceURL. * @param rmiServer The stub object to encode in the URL * @param attributes A Map containing environment parameters, * built from the Map specified at this object creation. **/ private void encodeStubInAddress(RMIServer rmiServer, Map attributes) throws IOException { final String protocol, host; final int port; if (address == null) { if (rmiServer instanceof javax.rmi.CORBA.Stub) protocol = "iiop"; else protocol = "rmi"; host = null; // will default to local host name port = 0; } else { protocol = address.getProtocol(); host = (address.getHost().equals("")) ? null : address.getHost(); port = address.getPort(); } final String urlPath = encodeStub(rmiServer, attributes); address = new JMXServiceURL(protocol, host, port, urlPath); } static boolean isIiopURL(JMXServiceURL directoryURL, boolean strict) throws MalformedURLException { String protocol = directoryURL.getProtocol(); if (protocol.equals("rmi")) return false; else if (protocol.equals("iiop")) return true; else if (strict) { throw new MalformedURLException("URL must have protocol " + "\"rmi\" or \"iiop\": \"" + protocol + "\""); } return false; } /** * Returns the IOR of the given rmiServer. **/ static String encodeStub(RMIServer rmiServer, Map env) throws IOException { if (rmiServer instanceof javax.rmi.CORBA.Stub) return "/ior/" + encodeIIOPStub(rmiServer, env); else return "/stub/" + encodeJRMPStub(rmiServer, env); } static String encodeJRMPStub(RMIServer rmiServer, Map env) throws IOException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); oout.writeObject(rmiServer); oout.close(); byte[] bytes = bout.toByteArray(); return byteArrayToBase64(bytes); } static String encodeIIOPStub(RMIServer rmiServer, Map env) throws IOException { try { javax.rmi.CORBA.Stub stub = (javax.rmi.CORBA.Stub) rmiServer; return stub._orb().object_to_string(stub); } catch (org.omg.CORBA.BAD_OPERATION x) { throw newIOException(x.getMessage(), x); } } /** * Object that we will bind to the registry. * This object is a stub connected to our RMIServerImpl. **/ private static RMIServer objectToBind(RMIServerImpl rmiServer, Map env) throws IOException { return RMIConnector. connectStub((RMIServer)rmiServer.toStub(),env); } private static RMIServerImpl newJRMPServer(Map env, int port) throws IOException { RMIClientSocketFactory csf = (RMIClientSocketFactory) env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE); RMIServerSocketFactory ssf = (RMIServerSocketFactory) env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE); return new RMIJRMPServerImpl(port, csf, ssf, env); } private static RMIServerImpl newIIOPServer(Map env) throws IOException { return new RMIIIOPServerImpl(env); } private static String byteArrayToBase64(byte[] a) { int aLen = a.length; int numFullGroups = aLen/3; int numBytesInPartialGroup = aLen - 3*numFullGroups; int resultLen = 4*((aLen + 2)/3); StringBuffer result = new StringBuffer(resultLen); // Translate all full groups from byte array elements to Base64 int inCursor = 0; for (int i=0; i<numFullGroups; i++) { int byte0 = a[inCursor++] & 0xff; int byte1 = a[inCursor++] & 0xff; int byte2 = a[inCursor++] & 0xff; result.append(intToAlpha[byte0 >> 2]); result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]); result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]); result.append(intToAlpha[byte2 & 0x3f]); } // Translate partial group if present if (numBytesInPartialGroup != 0) { int byte0 = a[inCursor++] & 0xff; result.append(intToAlpha[byte0 >> 2]); if (numBytesInPartialGroup == 1) { result.append(intToAlpha[(byte0 << 4) & 0x3f]); result.append("=="); } else { // assert numBytesInPartialGroup == 2; int byte1 = a[inCursor++] & 0xff; result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]); result.append(intToAlpha[(byte1 << 2)&0x3f]); result.append('='); } } // assert inCursor == a.length; // assert result.length() == resultLen; return result.toString(); } /** * This array is a lookup table that translates 6-bit positive integer * index values into their "Base64 Alphabet" equivalents as specified * in Table 1 of RFC 2045. */ private static final char intToAlpha[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** * Construct a new IOException with a nested exception. * The nested exception is set only if JDK >= 1.4 */ private static IOException newIOException(String message, Throwable cause) { final IOException x = new IOException(message); return EnvHelp.initCause(x,cause); } // Private variables // ----------------- private static ClassLogger logger = new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer"); private JMXServiceURL address; private RMIServerImpl rmiServerImpl; private final Map attributes; private ClassLoader defaultClassLoader = null; private String boundJndiUrl; // state private static final int CREATED = 0; private static final int STARTED = 1; private static final int STOPPED = 2; private int state = CREATED; private final static Set openedServers = new HashSet();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -