author | xdono |
Wed, 02 Jul 2008 12:55:45 -0700 | |
changeset 715 | f16baef3a20e |
parent 526 | 61ba2d5ea9da |
child 1156 | bbc2d15aaf7a |
permissions | -rw-r--r-- |
2 | 1 |
/* |
715 | 2 |
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
package javax.management.remote; |
|
27 |
||
28 |
import com.sun.jmx.mbeanserver.Util; |
|
29 |
import java.io.IOException; |
|
30 |
import java.net.MalformedURLException; |
|
31 |
import java.util.Collections; |
|
32 |
import java.util.HashMap; |
|
33 |
import java.util.Map; |
|
34 |
import java.util.Iterator; |
|
35 |
import java.util.ServiceLoader; |
|
36 |
import java.util.StringTokenizer; |
|
37 |
import java.security.AccessController; |
|
38 |
import java.security.PrivilegedAction; |
|
39 |
||
40 |
import com.sun.jmx.remote.util.ClassLogger; |
|
41 |
import com.sun.jmx.remote.util.EnvHelp; |
|
42 |
||
43 |
||
44 |
/** |
|
45 |
* <p>Factory to create JMX API connector clients. There |
|
46 |
* are no instances of this class.</p> |
|
47 |
* |
|
48 |
* <p>Connections are usually made using the {@link |
|
49 |
* #connect(JMXServiceURL) connect} method of this class. More |
|
50 |
* advanced applications can separate the creation of the connector |
|
51 |
* client, using {@link #newJMXConnector(JMXServiceURL, Map) |
|
52 |
* newJMXConnector} and the establishment of the connection itself, using |
|
53 |
* {@link JMXConnector#connect(Map)}.</p> |
|
54 |
* |
|
55 |
* <p>Each client is created by an instance of {@link |
|
56 |
* JMXConnectorProvider}. This instance is found as follows. Suppose |
|
57 |
* the given {@link JMXServiceURL} looks like |
|
58 |
* <code>"service:jmx:<em>protocol</em>:<em>remainder</em>"</code>. |
|
59 |
* Then the factory will attempt to find the appropriate {@link |
|
60 |
* JMXConnectorProvider} for <code><em>protocol</em></code>. Each |
|
61 |
* occurrence of the character <code>+</code> or <code>-</code> in |
|
62 |
* <code><em>protocol</em></code> is replaced by <code>.</code> or |
|
63 |
* <code>_</code>, respectively.</p> |
|
64 |
* |
|
65 |
* <p>A <em>provider package list</em> is searched for as follows:</p> |
|
66 |
* |
|
67 |
* <ol> |
|
68 |
* |
|
69 |
* <li>If the <code>environment</code> parameter to {@link |
|
70 |
* #newJMXConnector(JMXServiceURL, Map) newJMXConnector} contains the |
|
71 |
* key <code>jmx.remote.protocol.provider.pkgs</code> then the |
|
72 |
* associated value is the provider package list. |
|
73 |
* |
|
74 |
* <li>Otherwise, if the system property |
|
75 |
* <code>jmx.remote.protocol.provider.pkgs</code> exists, then its value |
|
76 |
* is the provider package list. |
|
77 |
* |
|
78 |
* <li>Otherwise, there is no provider package list. |
|
79 |
* |
|
80 |
* </ol> |
|
81 |
* |
|
82 |
* <p>The provider package list is a string that is interpreted as a |
|
83 |
* list of non-empty Java package names separated by vertical bars |
|
84 |
* (<code>|</code>). If the string is empty, then so is the provider |
|
85 |
* package list. If the provider package list is not a String, or if |
|
86 |
* it contains an element that is an empty string, a {@link |
|
87 |
* JMXProviderException} is thrown.</p> |
|
88 |
* |
|
89 |
* <p>If the provider package list exists and is not empty, then for |
|
90 |
* each element <code><em>pkg</em></code> of the list, the factory |
|
91 |
* will attempt to load the class |
|
92 |
* |
|
93 |
* <blockquote> |
|
94 |
* <code><em>pkg</em>.<em>protocol</em>.ClientProvider</code> |
|
95 |
* </blockquote> |
|
96 |
||
97 |
* <p>If the <code>environment</code> parameter to {@link |
|
98 |
* #newJMXConnector(JMXServiceURL, Map) newJMXConnector} contains the |
|
99 |
* key <code>jmx.remote.protocol.provider.class.loader</code> then the |
|
100 |
* associated value is the class loader to use to load the provider. |
|
101 |
* If the associated value is not an instance of {@link |
|
102 |
* java.lang.ClassLoader}, an {@link |
|
103 |
* java.lang.IllegalArgumentException} is thrown.</p> |
|
104 |
* |
|
105 |
* <p>If the <code>jmx.remote.protocol.provider.class.loader</code> |
|
106 |
* key is not present in the <code>environment</code> parameter, the |
|
107 |
* calling thread's context class loader is used.</p> |
|
108 |
* |
|
109 |
* <p>If the attempt to load this class produces a {@link |
|
110 |
* ClassNotFoundException}, the search for a handler continues with |
|
111 |
* the next element of the list.</p> |
|
112 |
* |
|
113 |
* <p>Otherwise, a problem with the provider found is signalled by a |
|
114 |
* {@link JMXProviderException} whose {@link |
|
115 |
* JMXProviderException#getCause() <em>cause</em>} indicates the underlying |
|
116 |
* exception, as follows:</p> |
|
117 |
* |
|
118 |
* <ul> |
|
119 |
* |
|
120 |
* <li>if the attempt to load the class produces an exception other |
|
121 |
* than <code>ClassNotFoundException</code>, that is the |
|
122 |
* <em>cause</em>; |
|
123 |
* |
|
124 |
* <li>if {@link Class#newInstance()} for the class produces an |
|
125 |
* exception, that is the <em>cause</em>. |
|
126 |
* |
|
127 |
* </ul> |
|
128 |
* |
|
129 |
* <p>If no provider is found by the above steps, including the |
|
130 |
* default case where there is no provider package list, then the |
|
131 |
* implementation will use its own provider for |
|
132 |
* <code><em>protocol</em></code>, or it will throw a |
|
133 |
* <code>MalformedURLException</code> if there is none. An |
|
134 |
* implementation may choose to find providers by other means. For |
|
135 |
* example, it may support the <a |
|
136 |
* href="{@docRoot}/../technotes/guides/jar/jar.html#Service Provider"> |
|
137 |
* JAR conventions for service providers</a>, where the service |
|
138 |
* interface is <code>JMXConnectorProvider</code>.</p> |
|
139 |
* |
|
140 |
* <p>Every implementation must support the RMI connector protocols, |
|
141 |
* specified with the string <code>rmi</code> or |
|
142 |
* <code>iiop</code>.</p> |
|
143 |
* |
|
144 |
* <p>Once a provider is found, the result of the |
|
145 |
* <code>newJMXConnector</code> method is the result of calling {@link |
|
146 |
* JMXConnectorProvider#newJMXConnector(JMXServiceURL,Map) newJMXConnector} |
|
147 |
* on the provider.</p> |
|
148 |
* |
|
149 |
* <p>The <code>Map</code> parameter passed to the |
|
150 |
* <code>JMXConnectorProvider</code> is a new read-only |
|
151 |
* <code>Map</code> that contains all the entries that were in the |
|
152 |
* <code>environment</code> parameter to {@link |
|
153 |
* #newJMXConnector(JMXServiceURL,Map) |
|
154 |
* JMXConnectorFactory.newJMXConnector}, if there was one. |
|
155 |
* Additionally, if the |
|
156 |
* <code>jmx.remote.protocol.provider.class.loader</code> key is not |
|
157 |
* present in the <code>environment</code> parameter, it is added to |
|
158 |
* the new read-only <code>Map</code>. The associated value is the |
|
159 |
* calling thread's context class loader.</p> |
|
160 |
* |
|
161 |
* @since 1.5 |
|
162 |
*/ |
|
163 |
public class JMXConnectorFactory { |
|
164 |
||
165 |
/** |
|
166 |
* <p>Name of the attribute that specifies the default class |
|
167 |
* loader. This class loader is used to deserialize return values and |
|
168 |
* exceptions from remote <code>MBeanServerConnection</code> |
|
169 |
* calls. The value associated with this attribute is an instance |
|
170 |
* of {@link ClassLoader}.</p> |
|
171 |
*/ |
|
172 |
public static final String DEFAULT_CLASS_LOADER = |
|
173 |
"jmx.remote.default.class.loader"; |
|
174 |
||
175 |
/** |
|
176 |
* <p>Name of the attribute that specifies the provider packages |
|
177 |
* that are consulted when looking for the handler for a protocol. |
|
178 |
* The value associated with this attribute is a string with |
|
179 |
* package names separated by vertical bars (<code>|</code>).</p> |
|
180 |
*/ |
|
181 |
public static final String PROTOCOL_PROVIDER_PACKAGES = |
|
182 |
"jmx.remote.protocol.provider.pkgs"; |
|
183 |
||
184 |
/** |
|
185 |
* <p>Name of the attribute that specifies the class |
|
186 |
* loader for loading protocol providers. |
|
187 |
* The value associated with this attribute is an instance |
|
188 |
* of {@link ClassLoader}.</p> |
|
189 |
*/ |
|
190 |
public static final String PROTOCOL_PROVIDER_CLASS_LOADER = |
|
191 |
"jmx.remote.protocol.provider.class.loader"; |
|
192 |
||
193 |
private static final String PROTOCOL_PROVIDER_DEFAULT_PACKAGE = |
|
194 |
"com.sun.jmx.remote.protocol"; |
|
195 |
||
196 |
private static final ClassLogger logger = |
|
197 |
new ClassLogger("javax.management.remote.misc", "JMXConnectorFactory"); |
|
198 |
||
199 |
/** There are no instances of this class. */ |
|
200 |
private JMXConnectorFactory() { |
|
201 |
} |
|
202 |
||
203 |
/** |
|
204 |
* <p>Creates a connection to the connector server at the given |
|
205 |
* address.</p> |
|
206 |
* |
|
207 |
* <p>This method is equivalent to {@link |
|
208 |
* #connect(JMXServiceURL,Map) connect(serviceURL, null)}.</p> |
|
209 |
* |
|
210 |
* @param serviceURL the address of the connector server to |
|
211 |
* connect to. |
|
212 |
* |
|
213 |
* @return a <code>JMXConnector</code> whose {@link |
|
214 |
* JMXConnector#connect connect} method has been called. |
|
215 |
* |
|
216 |
* @exception NullPointerException if <code>serviceURL</code> is null. |
|
217 |
* |
|
218 |
* @exception IOException if the connector client or the |
|
219 |
* connection cannot be made because of a communication problem. |
|
220 |
* |
|
221 |
* @exception SecurityException if the connection cannot be made |
|
222 |
* for security reasons. |
|
223 |
*/ |
|
224 |
public static JMXConnector connect(JMXServiceURL serviceURL) |
|
225 |
throws IOException { |
|
226 |
return connect(serviceURL, null); |
|
227 |
} |
|
228 |
||
229 |
/** |
|
230 |
* <p>Creates a connection to the connector server at the given |
|
231 |
* address.</p> |
|
232 |
* |
|
233 |
* <p>This method is equivalent to:</p> |
|
234 |
* |
|
235 |
* <pre> |
|
236 |
* JMXConnector conn = JMXConnectorFactory.newJMXConnector(serviceURL, |
|
237 |
* environment); |
|
238 |
* conn.connect(environment); |
|
239 |
* </pre> |
|
240 |
* |
|
241 |
* @param serviceURL the address of the connector server to connect to. |
|
242 |
* |
|
243 |
* @param environment a set of attributes to determine how the |
|
244 |
* connection is made. This parameter can be null. Keys in this |
|
245 |
* map must be Strings. The appropriate type of each associated |
|
246 |
* value depends on the attribute. The contents of |
|
247 |
* <code>environment</code> are not changed by this call. |
|
248 |
* |
|
249 |
* @return a <code>JMXConnector</code> representing the newly-made |
|
250 |
* connection. Each successful call to this method produces a |
|
251 |
* different object. |
|
252 |
* |
|
253 |
* @exception NullPointerException if <code>serviceURL</code> is null. |
|
254 |
* |
|
255 |
* @exception IOException if the connector client or the |
|
256 |
* connection cannot be made because of a communication problem. |
|
257 |
* |
|
258 |
* @exception SecurityException if the connection cannot be made |
|
259 |
* for security reasons. |
|
260 |
*/ |
|
261 |
public static JMXConnector connect(JMXServiceURL serviceURL, |
|
262 |
Map<String,?> environment) |
|
263 |
throws IOException { |
|
264 |
if (serviceURL == null) |
|
265 |
throw new NullPointerException("Null JMXServiceURL"); |
|
266 |
JMXConnector conn = newJMXConnector(serviceURL, environment); |
|
267 |
conn.connect(environment); |
|
268 |
return conn; |
|
269 |
} |
|
270 |
||
271 |
/** |
|
272 |
* <p>Creates a connector client for the connector server at the |
|
273 |
* given address. The resultant client is not connected until its |
|
274 |
* {@link JMXConnector#connect(Map) connect} method is called.</p> |
|
275 |
* |
|
276 |
* @param serviceURL the address of the connector server to connect to. |
|
277 |
* |
|
278 |
* @param environment a set of attributes to determine how the |
|
279 |
* connection is made. This parameter can be null. Keys in this |
|
280 |
* map must be Strings. The appropriate type of each associated |
|
281 |
* value depends on the attribute. The contents of |
|
282 |
* <code>environment</code> are not changed by this call. |
|
283 |
* |
|
284 |
* @return a <code>JMXConnector</code> representing the new |
|
285 |
* connector client. Each successful call to this method produces |
|
286 |
* a different object. |
|
287 |
* |
|
288 |
* @exception NullPointerException if <code>serviceURL</code> is null. |
|
289 |
* |
|
290 |
* @exception IOException if the connector client cannot be made |
|
291 |
* because of a communication problem. |
|
292 |
* |
|
293 |
* @exception MalformedURLException if there is no provider for the |
|
294 |
* protocol in <code>serviceURL</code>. |
|
295 |
* |
|
296 |
* @exception JMXProviderException if there is a provider for the |
|
297 |
* protocol in <code>serviceURL</code> but it cannot be used for |
|
298 |
* some reason. |
|
299 |
*/ |
|
300 |
public static JMXConnector newJMXConnector(JMXServiceURL serviceURL, |
|
301 |
Map<String,?> environment) |
|
302 |
throws IOException { |
|
303 |
Map<String, Object> envcopy; |
|
304 |
if (environment == null) |
|
305 |
envcopy = new HashMap<String, Object>(); |
|
306 |
else { |
|
307 |
EnvHelp.checkAttributes(environment); |
|
308 |
envcopy = new HashMap<String, Object>(environment); |
|
309 |
} |
|
310 |
||
311 |
final ClassLoader loader = resolveClassLoader(envcopy); |
|
312 |
final Class<JMXConnectorProvider> targetInterface = JMXConnectorProvider.class; |
|
313 |
final String protocol = serviceURL.getProtocol(); |
|
314 |
final String providerClassName = "ClientProvider"; |
|
315 |
||
316 |
JMXConnectorProvider provider = |
|
317 |
getProvider(serviceURL, envcopy, providerClassName, |
|
318 |
targetInterface, loader); |
|
319 |
||
320 |
IOException exception = null; |
|
321 |
if (provider == null) { |
|
322 |
// Loader is null when context class loader is set to null |
|
323 |
// and no loader has been provided in map. |
|
324 |
// com.sun.jmx.remote.util.Service class extracted from j2se |
|
325 |
// provider search algorithm doesn't handle well null classloader. |
|
326 |
if (loader != null) { |
|
327 |
try { |
|
328 |
JMXConnector connection = |
|
329 |
getConnectorAsService(loader, serviceURL, envcopy); |
|
330 |
if (connection != null) |
|
331 |
return connection; |
|
332 |
} catch (JMXProviderException e) { |
|
333 |
throw e; |
|
334 |
} catch (IOException e) { |
|
335 |
exception = e; |
|
336 |
} |
|
337 |
} |
|
338 |
provider = |
|
339 |
getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE, |
|
340 |
JMXConnectorFactory.class.getClassLoader(), |
|
341 |
providerClassName, targetInterface); |
|
342 |
} |
|
343 |
||
344 |
if (provider == null) { |
|
345 |
MalformedURLException e = |
|
346 |
new MalformedURLException("Unsupported protocol: " + protocol); |
|
347 |
if (exception == null) { |
|
348 |
throw e; |
|
349 |
} else { |
|
350 |
throw EnvHelp.initCause(e, exception); |
|
351 |
} |
|
352 |
} |
|
353 |
||
354 |
envcopy = Collections.unmodifiableMap(envcopy); |
|
355 |
||
356 |
return provider.newJMXConnector(serviceURL, envcopy); |
|
357 |
} |
|
358 |
||
359 |
private static String resolvePkgs(Map env) throws JMXProviderException { |
|
360 |
||
361 |
Object pkgsObject = null; |
|
362 |
||
363 |
if (env != null) |
|
364 |
pkgsObject = env.get(PROTOCOL_PROVIDER_PACKAGES); |
|
365 |
||
366 |
if (pkgsObject == null) |
|
367 |
pkgsObject = |
|
368 |
AccessController.doPrivileged(new PrivilegedAction<Object>() { |
|
369 |
public Object run() { |
|
370 |
return System.getProperty(PROTOCOL_PROVIDER_PACKAGES); |
|
371 |
} |
|
372 |
}); |
|
373 |
||
374 |
if (pkgsObject == null) |
|
375 |
return null; |
|
376 |
||
377 |
if (!(pkgsObject instanceof String)) { |
|
378 |
final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES + |
|
379 |
" parameter is not a String: " + |
|
380 |
pkgsObject.getClass().getName(); |
|
381 |
throw new JMXProviderException(msg); |
|
382 |
} |
|
383 |
||
384 |
final String pkgs = (String) pkgsObject; |
|
385 |
if (pkgs.trim().equals("")) |
|
386 |
return null; |
|
387 |
||
388 |
// pkgs may not contain an empty element |
|
389 |
if (pkgs.startsWith("|") || pkgs.endsWith("|") || |
|
390 |
pkgs.indexOf("||") >= 0) { |
|
391 |
final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES + |
|
392 |
" contains an empty element: " + pkgs; |
|
393 |
throw new JMXProviderException(msg); |
|
394 |
} |
|
395 |
||
396 |
return pkgs; |
|
397 |
} |
|
398 |
||
399 |
static <T> T getProvider(JMXServiceURL serviceURL, |
|
400 |
Map<String, Object> environment, |
|
401 |
String providerClassName, |
|
402 |
Class<T> targetInterface, |
|
403 |
ClassLoader loader) |
|
404 |
throws IOException { |
|
405 |
||
406 |
final String protocol = serviceURL.getProtocol(); |
|
407 |
||
408 |
final String pkgs = resolvePkgs(environment); |
|
409 |
||
410 |
T instance = null; |
|
411 |
||
412 |
if (pkgs != null) { |
|
413 |
environment.put(PROTOCOL_PROVIDER_CLASS_LOADER, loader); |
|
414 |
||
415 |
instance = |
|
416 |
getProvider(protocol, pkgs, loader, providerClassName, |
|
417 |
targetInterface); |
|
418 |
} |
|
419 |
||
420 |
return instance; |
|
421 |
} |
|
422 |
||
423 |
static <T> Iterator<T> getProviderIterator(final Class<T> providerClass, |
|
424 |
final ClassLoader loader) { |
|
425 |
ServiceLoader<T> serviceLoader = |
|
426 |
ServiceLoader.load(providerClass, |
|
427 |
loader); |
|
428 |
return serviceLoader.iterator(); |
|
429 |
} |
|
430 |
||
431 |
private static JMXConnector getConnectorAsService(ClassLoader loader, |
|
432 |
JMXServiceURL url, |
|
433 |
Map<String, ?> map) |
|
434 |
throws IOException { |
|
435 |
||
436 |
Iterator<JMXConnectorProvider> providers = |
|
437 |
getProviderIterator(JMXConnectorProvider.class, loader); |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
438 |
JMXConnector connection; |
2 | 439 |
IOException exception = null; |
440 |
while(providers.hasNext()) { |
|
441 |
try { |
|
442 |
connection = providers.next().newJMXConnector(url, map); |
|
443 |
return connection; |
|
444 |
} catch (JMXProviderException e) { |
|
445 |
throw e; |
|
446 |
} catch (Exception e) { |
|
447 |
if (logger.traceOn()) |
|
448 |
logger.trace("getConnectorAsService", |
|
449 |
"URL[" + url + |
|
450 |
"] Service provider exception: " + e); |
|
451 |
if (!(e instanceof MalformedURLException)) { |
|
452 |
if (exception == null) { |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
453 |
if (e instanceof IOException) { |
2 | 454 |
exception = (IOException) e; |
455 |
} else { |
|
456 |
exception = EnvHelp.initCause( |
|
457 |
new IOException(e.getMessage()), e); |
|
458 |
} |
|
459 |
} |
|
460 |
} |
|
461 |
continue; |
|
462 |
} |
|
463 |
} |
|
464 |
if (exception == null) |
|
465 |
return null; |
|
466 |
else |
|
467 |
throw exception; |
|
468 |
} |
|
469 |
||
470 |
static <T> T getProvider(String protocol, |
|
471 |
String pkgs, |
|
472 |
ClassLoader loader, |
|
473 |
String providerClassName, |
|
474 |
Class<T> targetInterface) |
|
475 |
throws IOException { |
|
476 |
||
477 |
StringTokenizer tokenizer = new StringTokenizer(pkgs, "|"); |
|
478 |
||
479 |
while (tokenizer.hasMoreTokens()) { |
|
480 |
String pkg = tokenizer.nextToken(); |
|
481 |
String className = (pkg + "." + protocol2package(protocol) + |
|
482 |
"." + providerClassName); |
|
483 |
Class<?> providerClass; |
|
484 |
try { |
|
485 |
providerClass = Class.forName(className, true, loader); |
|
486 |
} catch (ClassNotFoundException e) { |
|
487 |
//Add trace. |
|
488 |
continue; |
|
489 |
} |
|
490 |
||
491 |
if (!targetInterface.isAssignableFrom(providerClass)) { |
|
492 |
final String msg = |
|
493 |
"Provider class does not implement " + |
|
494 |
targetInterface.getName() + ": " + |
|
495 |
providerClass.getName(); |
|
496 |
throw new JMXProviderException(msg); |
|
497 |
} |
|
498 |
||
499 |
// We have just proved that this cast is correct |
|
500 |
Class<? extends T> providerClassT = Util.cast(providerClass); |
|
501 |
try { |
|
502 |
return providerClassT.newInstance(); |
|
503 |
} catch (Exception e) { |
|
504 |
final String msg = |
|
505 |
"Exception when instantiating provider [" + className + |
|
506 |
"]"; |
|
507 |
throw new JMXProviderException(msg, e); |
|
508 |
} |
|
509 |
} |
|
510 |
||
511 |
return null; |
|
512 |
} |
|
513 |
||
514 |
static ClassLoader resolveClassLoader(Map environment) { |
|
515 |
ClassLoader loader = null; |
|
516 |
||
517 |
if (environment != null) { |
|
518 |
try { |
|
519 |
loader = (ClassLoader) |
|
520 |
environment.get(PROTOCOL_PROVIDER_CLASS_LOADER); |
|
521 |
} catch (ClassCastException e) { |
|
522 |
final String msg = |
|
523 |
"The ClassLoader supplied in the environment map using " + |
|
524 |
"the " + PROTOCOL_PROVIDER_CLASS_LOADER + |
|
525 |
" attribute is not an instance of java.lang.ClassLoader"; |
|
526 |
throw new IllegalArgumentException(msg); |
|
527 |
} |
|
528 |
} |
|
529 |
||
530 |
if (loader == null) |
|
531 |
loader = |
|
532 |
AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { |
|
533 |
public ClassLoader run() { |
|
534 |
return |
|
535 |
Thread.currentThread().getContextClassLoader(); |
|
536 |
} |
|
537 |
}); |
|
538 |
||
539 |
return loader; |
|
540 |
} |
|
541 |
||
542 |
private static String protocol2package(String protocol) { |
|
543 |
return protocol.replace('+', '.').replace('-', '_'); |
|
544 |
} |
|
545 |
} |