KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > remote > JMXConnectorServerFactory


1 /*
2  * @(#)JMXConnectorServerFactory.java 1.17 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management.remote;
9
10 import java.io.IOException JavaDoc;
11 import java.net.MalformedURLException JavaDoc;
12 import java.util.Collections JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import javax.management.MBeanServer JavaDoc;
18 import javax.management.ObjectName JavaDoc;
19
20 import com.sun.jmx.remote.util.ClassLogger;
21 import com.sun.jmx.remote.util.EnvHelp;
22
23 /**
24  * <p>Factory to create JMX API connector servers. There
25  * are no instances of this class.</p>
26  *
27  * <p>Each connector server is created by an instance of {@link
28  * JMXConnectorServerProvider}. This instance is found as follows. Suppose
29  * the given {@link JMXServiceURL} looks like
30  * <code>"service:jmx:<em>protocol</em>:<em>remainder</em>"</code>.
31  * Then the factory will attempt to find the appropriate {@link
32  * JMXConnectorServerProvider} for <code><em>protocol</em></code>. Each
33  * occurrence of the character <code>+</code> or <code>-</code> in
34  * <code><em>protocol</em></code> is replaced by <code>.</code> or
35  * <code>_</code>, respectively.</p>
36  *
37  * <p>A <em>provider package list</em> is searched for as follows:</p>
38  *
39  * <ol>
40  *
41  * <li>If the <code>environment</code> parameter to {@link
42  * #newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)
43  * newJMXConnectorServer} contains the key
44  * <code>jmx.remote.protocol.provider.pkgs</code> then the associated
45  * value is the provider package list.
46  *
47  * <li>Otherwise, if the system property
48  * <code>jmx.remote.protocol.provider.pkgs</code> exists, then its value
49  * is the provider package list.
50  *
51  * <li>Otherwise, there is no provider package list.
52  *
53  * </ol>
54  *
55  * <p>The provider package list is a string that is interpreted as a
56  * list of non-empty Java package names separated by vertical bars
57  * (<code>|</code>). If the string is empty, then so is the provider
58  * package list. If the provider package list is not a String, or if
59  * it contains an element that is an empty string, a {@link
60  * JMXProviderException} is thrown.</p>
61  *
62  * <p>If the provider package list exists and is not empty, then for
63  * each element <code><em>pkg</em></code> of the list, the factory
64  * will attempt to load the class
65  *
66  * <blockquote>
67  * <code><em>pkg</em>.<em>protocol</em>.ServerProvider</code>
68  * </blockquote>
69
70  * <p>If the <code>environment</code> parameter to {@link
71  * #newJMXConnectorServer(JMXServiceURL, Map, MBeanServer)
72  * newJMXConnectorServer} contains the key
73  * <code>jmx.remote.protocol.provider.class.loader</code> then the
74  * associated value is the class loader to use to load the provider.
75  * If the associated value is not an instance of {@link
76  * java.lang.ClassLoader}, an {@link
77  * java.lang.IllegalArgumentException} is thrown.</p>
78  *
79  * <p>If the <code>jmx.remote.protocol.provider.class.loader</code>
80  * key is not present in the <code>environment</code> parameter, the
81  * calling thread's context class loader is used.</p>
82  *
83  * <p>If the attempt to load this class produces a {@link
84  * ClassNotFoundException}, the search for a handler continues with
85  * the next element of the list.</p>
86  *
87  * <p>Otherwise, a problem with the provider found is signalled by a
88  * {@link JMXProviderException} whose {@link
89  * JMXProviderException#getCause() <em>cause</em>} indicates the
90  * underlying exception, as follows:</p>
91  *
92  * <ul>
93  *
94  * <li>if the attempt to load the class produces an exception other
95  * than <code>ClassNotFoundException</code>, that is the
96  * <em>cause</em>;
97  *
98  * <li>if {@link Class#newInstance()} for the class produces an
99  * exception, that is the <em>cause</em>.
100  *
101  * </ul>
102  *
103  * <p>If no provider is found by the above steps, including the
104  * default case where there is no provider package list, then the
105  * implementation will use its own provider for
106  * <code><em>protocol</em></code>, or it will throw a
107  * <code>MalformedURLException</code> if there is none. An
108  * implementation may choose to find providers by other means. For
109  * example, it may support the <a
110  * HREF="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service Provider">
111  * JAR conventions for service providers</a>, where the service
112  * interface is <code>JMXConnectorServerProvider</code>.</p>
113  *
114  * <p>Every implementation must support the RMI connector protocols,
115  * specified with the string <code>rmi</code> or
116  * <code>iiop</code>.</p>
117  *
118  * <p>Once a provider is found, the result of the
119  * <code>newJMXConnectorServer</code> method is the result of calling
120  * {@link
121  * JMXConnectorServerProvider#newJMXConnectorServer(JMXServiceURL,
122  * Map, MBeanServer) newJMXConnectorServer} on the provider.</p>
123  *
124  * <p>The <code>Map</code> parameter passed to the
125  * <code>JMXConnectorServerProvider</code> is a new read-only
126  * <code>Map</code> that contains all the entries that were in the
127  * <code>environment</code> parameter to {@link
128  * #newJMXConnectorServer(JMXServiceURL,Map,MBeanServer)
129  * JMXConnectorServerFactory.newJMXConnectorServer}, if there was one.
130  * Additionally, if the
131  * <code>jmx.remote.protocol.provider.class.loader</code> key is not
132  * present in the <code>environment</code> parameter, it is added to
133  * the new read-only <code>Map</code>. The associated value is the
134  * calling thread's context class loader.</p>
135  *
136  * @since 1.5
137  * @since.unbundled 1.0
138  */

139 public class JMXConnectorServerFactory {
140
141     /**
142      * <p>Name of the attribute that specifies the default class
143      * loader. This class loader is used to deserialize objects in
144      * requests received from the client, possibly after consulting an
145      * MBean-specific class loader. The value associated with this
146      * attribute is an instance of {@link ClassLoader}.</p>
147      */

148     public static final String JavaDoc DEFAULT_CLASS_LOADER =
149     JMXConnectorFactory.DEFAULT_CLASS_LOADER;
150
151     /**
152      * <p>Name of the attribute that specifies the default class
153      * loader MBean name. This class loader is used to deserialize objects in
154      * requests received from the client, possibly after consulting an
155      * MBean-specific class loader. The value associated with this
156      * attribute is an instance of {@link ObjectName}.</p>
157      */

158     public static final String JavaDoc DEFAULT_CLASS_LOADER_NAME =
159     "jmx.remote.default.class.loader.name";
160
161     /**
162      * <p>Name of the attribute that specifies the provider packages
163      * that are consulted when looking for the handler for a protocol.
164      * The value associated with this attribute is a string with
165      * package names separated by vertical bars (<code>|</code>).</p>
166      */

167     public static final String JavaDoc PROTOCOL_PROVIDER_PACKAGES =
168         "jmx.remote.protocol.provider.pkgs";
169
170     /**
171      * <p>Name of the attribute that specifies the class
172      * loader for loading protocol providers.
173      * The value associated with this attribute is an instance
174      * of {@link ClassLoader}.</p>
175      */

176     public static final String JavaDoc PROTOCOL_PROVIDER_CLASS_LOADER =
177         "jmx.remote.protocol.provider.class.loader";
178
179     private static final String JavaDoc PROTOCOL_PROVIDER_DEFAULT_PACKAGE =
180     "com.sun.jmx.remote.protocol";
181     
182     private static final ClassLogger logger =
183     new ClassLogger("javax.management.remote.misc","JMXConnectorServerFactory");
184     
185     /** There are no instances of this class. */
186     private JMXConnectorServerFactory() {
187     }
188
189     private static JMXConnectorServer JavaDoc
190     getConnectorServerAsService(ClassLoader JavaDoc loader,
191                     JMXServiceURL JavaDoc url,
192                     Map JavaDoc map,
193                     MBeanServer JavaDoc mbs)
194     throws IllegalArgumentException JavaDoc, JMXProviderException JavaDoc {
195     Iterator JavaDoc providers =
196         JMXConnectorFactory.getProviderIterator(JMXConnectorServerProvider JavaDoc.class,
197                             loader);
198     JMXConnectorServerProvider JavaDoc provider = null;
199     JMXConnectorServer JavaDoc connection = null;
200     while(providers.hasNext()) {
201         provider =
202         (JMXConnectorServerProvider JavaDoc) providers.next();
203         try {
204         connection = provider.newJMXConnectorServer(url, map, mbs);
205         return connection;
206         } catch (JMXProviderException JavaDoc e) {
207         throw e;
208         }
209         catch (Exception JavaDoc e) {
210         if (logger.traceOn())
211             logger.trace("getConnectorAsService",
212                  "URL[" + url +
213                  "] Service provider exception " + e);
214         continue;
215         }
216     }
217     return null;
218     }
219     
220     /**
221      * <p>Creates a connector server at the given address. The
222      * resultant server is not started until its {@link
223      * JMXConnectorServer#start() start} method is called.</p>
224      *
225      * @param serviceURL the address of the new connector server. The
226      * actual address of the new connector server, as returned by its
227      * {@link JMXConnectorServer#getAddress() getAddress} method, will
228      * not necessarily be exactly the same. For example, it might
229      * include a port number if the original address did not.
230      *
231      * @param environment a set of attributes to control the new
232      * connector server's behaviour. This parameter can be null.
233      * Keys in this map must be Strings. The appropriate type of each
234      * associated value depends on the attribute. The contents of
235      * <code>environment</code> are not changed by this call.
236      *
237      * @param mbeanServer the MBean server that this connector server
238      * is attached to. Null if this connector server will be attached
239      * to an MBean server by being registered in it.
240      *
241      * @return a <code>JMXConnectorServer</code> representing the new
242      * connector server. Each successful call to this method produces
243      * a different object.
244      *
245      * @exception NullPointerException if <code>serviceURL</code> is null.
246      *
247      * @exception IOException if the connector server cannot be made
248      * because of a communication problem.
249      *
250      * @exception MalformedURLException if there is no provider for the
251      * protocol in <code>serviceURL</code>.
252      *
253      * @exception JMXProviderException if there is a provider for the
254      * protocol in <code>serviceURL</code> but it cannot be used for
255      * some reason.
256      */

257     public static JMXConnectorServer JavaDoc
258     newJMXConnectorServer(JMXServiceURL JavaDoc serviceURL,
259                   Map JavaDoc<String JavaDoc,?> environment,
260                   MBeanServer JavaDoc mbeanServer)
261             throws IOException JavaDoc {
262     if (environment == null)
263         environment = new HashMap JavaDoc();
264     else {
265         EnvHelp.checkAttributes(environment);
266         environment = new HashMap JavaDoc(environment);
267     }
268
269     final Class JavaDoc targetInterface = JMXConnectorServerProvider JavaDoc.class;
270     final ClassLoader JavaDoc loader =
271         JMXConnectorFactory.resolveClassLoader(environment);
272     final String JavaDoc protocol = serviceURL.getProtocol();
273     final String JavaDoc providerClassName = "ServerProvider";
274     
275     JMXConnectorServerProvider JavaDoc provider =
276         (JMXConnectorServerProvider JavaDoc)
277         JMXConnectorFactory.getProvider(serviceURL, environment,
278                         providerClassName,
279                         targetInterface, loader);
280     if(provider == null) {
281         // Loader is null when context class loader is set to null
282
// and no loader has been provided in map.
283
// com.sun.jmx.remote.util.Service class extracted from j2se
284
// provider search algorithm doesn't handle well null classloader.
285
if(loader != null) {
286         JMXConnectorServer JavaDoc connection =
287             getConnectorServerAsService(loader,
288                         serviceURL,
289                         environment,
290                         mbeanServer);
291         if(connection != null)
292             return connection;
293         }
294     
295         provider = (JMXConnectorServerProvider JavaDoc)
296         JMXConnectorFactory.getProvider(protocol,
297                         PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
298                         JMXConnectorFactory JavaDoc.class.getClassLoader(),
299                         providerClassName,
300                         targetInterface);
301     }
302     
303     if(provider == null)
304         throw new MalformedURLException JavaDoc("Unsupported protocol: " +
305                         protocol);
306     
307     environment = Collections.unmodifiableMap(environment);
308         
309         return provider.newJMXConnectorServer(serviceURL, environment,
310                           mbeanServer);
311     }
312 }
313
Popular Tags