001: /*
002: * Copyright (C) The MX4J Contributors.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the MX4J License version 1.0.
006: * See the terms of the MX4J License in the documentation provided with this software.
007: */
008:
009: package javax.management.remote.rmi;
010:
011: import java.io.IOException;
012: import java.net.MalformedURLException;
013: import java.util.Collections;
014: import java.util.HashMap;
015: import java.util.Map;
016: import javax.management.InstanceNotFoundException;
017: import javax.management.MBeanServer;
018: import javax.management.ObjectName;
019: import javax.management.remote.JMXConnector;
020: import javax.management.remote.JMXConnectorServer;
021: import javax.management.remote.JMXConnectorServerFactory;
022: import javax.management.remote.JMXServiceURL;
023:
024: import mx4j.log.Log;
025: import mx4j.log.Logger;
026: import mx4j.remote.ConnectionResolver;
027: import mx4j.remote.MX4JRemoteUtils;
028:
029: /**
030: * @version $Revision: 1.16 $
031: */
032: public class RMIConnectorServer extends JMXConnectorServer {
033: public static final String JNDI_REBIND_ATTRIBUTE = "jmx.remote.jndi.rebind";
034: public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE = "jmx.remote.rmi.client.socket.factory";
035: public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE = "jmx.remote.rmi.server.socket.factory";
036:
037: private JMXServiceURL url;
038: private final Map environment;
039: private RMIServerImpl rmiServer;
040: private final ClassLoader defaultClassLoader;
041: private boolean active;
042: private boolean stopped;
043:
044: public RMIConnectorServer(JMXServiceURL url, Map environment)
045: throws IOException {
046: this (url, environment, null, null);
047: }
048:
049: public RMIConnectorServer(JMXServiceURL url, Map environment,
050: MBeanServer server) throws IOException {
051: this (url, environment, null, server);
052: }
053:
054: public RMIConnectorServer(JMXServiceURL url, Map environment,
055: RMIServerImpl rmiServer, MBeanServer server)
056: throws IOException {
057: super (server);
058: if (url == null)
059: throw new IllegalArgumentException(
060: "JMXServiceURL cannot be null");
061: this .url = url;
062: this .environment = environment == null ? new HashMap()
063: : new HashMap(environment);
064: this .rmiServer = rmiServer;
065: this .defaultClassLoader = findDefaultClassLoader(
066: this .environment, server);
067: }
068:
069: private ClassLoader findDefaultClassLoader(Map environment,
070: MBeanServer server) throws IllegalArgumentException {
071: Object loader = environment
072: .get(JMXConnectorServerFactory.DEFAULT_CLASS_LOADER);
073: Object loaderName = environment
074: .get(JMXConnectorServerFactory.DEFAULT_CLASS_LOADER_NAME);
075: if (loader != null && loaderName != null)
076: throw new IllegalArgumentException(
077: "Environment properties "
078: + JMXConnectorServerFactory.DEFAULT_CLASS_LOADER
079: + " and "
080: + JMXConnectorServerFactory.DEFAULT_CLASS_LOADER_NAME
081: + " cannot be both defined");
082:
083: if (loader != null) {
084: if (!(loader instanceof ClassLoader))
085: throw new IllegalArgumentException(
086: "Environment property "
087: + JMXConnectorServerFactory.DEFAULT_CLASS_LOADER
088: + " must be a ClassLoader");
089: else
090: return (ClassLoader) loader;
091: }
092:
093: if (loaderName != null) {
094: if (!(loaderName instanceof ObjectName))
095: throw new IllegalArgumentException(
096: "Environment property "
097: + JMXConnectorServerFactory.DEFAULT_CLASS_LOADER_NAME
098: + " must be an ObjectName");
099: ObjectName name = (ObjectName) loaderName;
100: try {
101: if (!server.isInstanceOf(name, ClassLoader.class
102: .getName()))
103: throw new InstanceNotFoundException();
104: return server.getClassLoader((ObjectName) loader);
105: } catch (InstanceNotFoundException x) {
106: throw new IllegalArgumentException(
107: "ObjectName "
108: + name
109: + " defined by environment property "
110: + JMXConnectorServerFactory.DEFAULT_CLASS_LOADER_NAME
111: + " must name a ClassLoader");
112: }
113: }
114:
115: return Thread.currentThread().getContextClassLoader();
116: }
117:
118: public JMXServiceURL getAddress() {
119: return url;
120: }
121:
122: public Map getAttributes() {
123: Map env = MX4JRemoteUtils
124: .removeNonSerializableEntries(environment);
125: return Collections.unmodifiableMap(env);
126: }
127:
128: public boolean isActive() {
129: return active;
130: }
131:
132: private boolean isStopped() {
133: return stopped;
134: }
135:
136: public synchronized void start() throws IOException {
137: Logger logger = getLogger();
138:
139: if (isActive()) {
140: if (logger.isEnabledFor(Logger.TRACE))
141: logger
142: .trace("This RMIConnectorServer has already been started");
143: return;
144: }
145: if (isStopped()) {
146: if (logger.isEnabledFor(Logger.TRACE))
147: logger
148: .trace("This RMIConnectorServer has already been stopped");
149: throw new IOException(
150: "This RMIConnectorServer has already been stopped");
151: }
152:
153: MBeanServer server = getMBeanServer();
154: if (server == null)
155: throw new IllegalStateException(
156: "This RMIConnectorServer is not attached to an MBeanServer");
157:
158: JMXServiceURL address = getAddress();
159: String protocol = address.getProtocol();
160: ConnectionResolver resolver = ConnectionResolver
161: .newConnectionResolver(protocol, environment);
162: if (rmiServer == null) {
163: if (resolver == null)
164: throw new MalformedURLException(
165: "Unsupported protocol: " + protocol);
166: rmiServer = (RMIServerImpl) resolver.createServer(address,
167: environment);
168: }
169:
170: rmiServer.setRMIConnectorServer(this );
171: rmiServer.setMBeanServer(server);
172: rmiServer.setDefaultClassLoader(defaultClassLoader);
173:
174: rmiServer.export();
175:
176: // Replace the JMXServiceURL, as it can now contain the encoded stub/ior
177: url = resolver.bindServer(rmiServer, address, environment);
178:
179: active = true;
180:
181: if (logger.isEnabledFor(Logger.INFO))
182: logger.info("RMIConnectorServer started at: " + url);
183: }
184:
185: public synchronized void stop() throws IOException {
186: if (isStopped())
187: return;
188:
189: stopped = true;
190: active = false;
191:
192: if (rmiServer != null)
193: rmiServer.close();
194:
195: JMXServiceURL address = getAddress();
196: String protocol = address.getProtocol();
197: ConnectionResolver resolver = ConnectionResolver
198: .newConnectionResolver(protocol, environment);
199: if (resolver == null)
200: throw new MalformedURLException("Unsupported protocol: "
201: + protocol);
202: resolver.unbindServer(rmiServer, address, environment);
203: resolver.destroyServer(rmiServer, address, environment);
204:
205: Logger logger = getLogger();
206: if (logger.isEnabledFor(Logger.INFO))
207: logger.info("RMIConnectorServer stopped at: " + address);
208: }
209:
210: public JMXConnector toJMXConnector(Map env) throws IOException {
211: if (!isActive())
212: throw new IllegalStateException(
213: "This JMXConnectorServer has not been started");
214: return super .toJMXConnector(env);
215: }
216:
217: protected void connectionOpened(String connectionId,
218: String message, Object userData) {
219: super .connectionOpened(connectionId, message, userData);
220: }
221:
222: protected void connectionClosed(String connectionId,
223: String message, Object userData) {
224: super .connectionClosed(connectionId, message, userData);
225: }
226:
227: protected void connectionFailed(String connectionId,
228: String message, Object userData) {
229: super .connectionFailed(connectionId, message, userData);
230: }
231:
232: private Logger getLogger() {
233: return Log.getLogger(getClass().getName());
234: }
235: }
|