author | alanb |
Thu, 20 Dec 2012 20:29:59 +0000 | |
changeset 14917 | bf08557604f8 |
parent 5506 | 202f599c92aa |
child 18187 | a798516cf58d |
permissions | -rw-r--r-- |
2 | 1 |
/* |
5506 | 2 |
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 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 |
* |
|
14917
bf08557604f8
8001048: JSR-160: Allow IIOP transport to be optional
alanb
parents:
5506
diff
changeset
|
140 |
* <p>Every implementation must support the RMI connector protocol with |
bf08557604f8
8001048: JSR-160: Allow IIOP transport to be optional
alanb
parents:
5506
diff
changeset
|
141 |
* the default RMI transport, specified with string <code>rmi</code>. |
bf08557604f8
8001048: JSR-160: Allow IIOP transport to be optional
alanb
parents:
5506
diff
changeset
|
142 |
* An implementation may optionally support the RMI connector protocol |
bf08557604f8
8001048: JSR-160: Allow IIOP transport to be optional
alanb
parents:
5506
diff
changeset
|
143 |
* with the RMI/IIOP transport, specified with the string |
2 | 144 |
* <code>iiop</code>.</p> |
145 |
* |
|
146 |
* <p>Once a provider is found, the result of the |
|
147 |
* <code>newJMXConnector</code> method is the result of calling {@link |
|
148 |
* JMXConnectorProvider#newJMXConnector(JMXServiceURL,Map) newJMXConnector} |
|
149 |
* on the provider.</p> |
|
150 |
* |
|
151 |
* <p>The <code>Map</code> parameter passed to the |
|
152 |
* <code>JMXConnectorProvider</code> is a new read-only |
|
153 |
* <code>Map</code> that contains all the entries that were in the |
|
154 |
* <code>environment</code> parameter to {@link |
|
155 |
* #newJMXConnector(JMXServiceURL,Map) |
|
156 |
* JMXConnectorFactory.newJMXConnector}, if there was one. |
|
157 |
* Additionally, if the |
|
158 |
* <code>jmx.remote.protocol.provider.class.loader</code> key is not |
|
159 |
* present in the <code>environment</code> parameter, it is added to |
|
160 |
* the new read-only <code>Map</code>. The associated value is the |
|
161 |
* calling thread's context class loader.</p> |
|
162 |
* |
|
163 |
* @since 1.5 |
|
164 |
*/ |
|
165 |
public class JMXConnectorFactory { |
|
166 |
||
167 |
/** |
|
168 |
* <p>Name of the attribute that specifies the default class |
|
169 |
* loader. This class loader is used to deserialize return values and |
|
170 |
* exceptions from remote <code>MBeanServerConnection</code> |
|
171 |
* calls. The value associated with this attribute is an instance |
|
172 |
* of {@link ClassLoader}.</p> |
|
173 |
*/ |
|
174 |
public static final String DEFAULT_CLASS_LOADER = |
|
175 |
"jmx.remote.default.class.loader"; |
|
176 |
||
177 |
/** |
|
178 |
* <p>Name of the attribute that specifies the provider packages |
|
179 |
* that are consulted when looking for the handler for a protocol. |
|
180 |
* The value associated with this attribute is a string with |
|
181 |
* package names separated by vertical bars (<code>|</code>).</p> |
|
182 |
*/ |
|
183 |
public static final String PROTOCOL_PROVIDER_PACKAGES = |
|
184 |
"jmx.remote.protocol.provider.pkgs"; |
|
185 |
||
186 |
/** |
|
187 |
* <p>Name of the attribute that specifies the class |
|
188 |
* loader for loading protocol providers. |
|
189 |
* The value associated with this attribute is an instance |
|
190 |
* of {@link ClassLoader}.</p> |
|
191 |
*/ |
|
192 |
public static final String PROTOCOL_PROVIDER_CLASS_LOADER = |
|
193 |
"jmx.remote.protocol.provider.class.loader"; |
|
194 |
||
195 |
private static final String PROTOCOL_PROVIDER_DEFAULT_PACKAGE = |
|
196 |
"com.sun.jmx.remote.protocol"; |
|
197 |
||
198 |
private static final ClassLogger logger = |
|
199 |
new ClassLogger("javax.management.remote.misc", "JMXConnectorFactory"); |
|
200 |
||
201 |
/** There are no instances of this class. */ |
|
202 |
private JMXConnectorFactory() { |
|
203 |
} |
|
204 |
||
205 |
/** |
|
206 |
* <p>Creates a connection to the connector server at the given |
|
207 |
* address.</p> |
|
208 |
* |
|
209 |
* <p>This method is equivalent to {@link |
|
210 |
* #connect(JMXServiceURL,Map) connect(serviceURL, null)}.</p> |
|
211 |
* |
|
212 |
* @param serviceURL the address of the connector server to |
|
213 |
* connect to. |
|
214 |
* |
|
215 |
* @return a <code>JMXConnector</code> whose {@link |
|
216 |
* JMXConnector#connect connect} method has been called. |
|
217 |
* |
|
218 |
* @exception NullPointerException if <code>serviceURL</code> is null. |
|
219 |
* |
|
220 |
* @exception IOException if the connector client or the |
|
221 |
* connection cannot be made because of a communication problem. |
|
222 |
* |
|
223 |
* @exception SecurityException if the connection cannot be made |
|
224 |
* for security reasons. |
|
225 |
*/ |
|
226 |
public static JMXConnector connect(JMXServiceURL serviceURL) |
|
227 |
throws IOException { |
|
228 |
return connect(serviceURL, null); |
|
229 |
} |
|
230 |
||
231 |
/** |
|
232 |
* <p>Creates a connection to the connector server at the given |
|
233 |
* address.</p> |
|
234 |
* |
|
235 |
* <p>This method is equivalent to:</p> |
|
236 |
* |
|
237 |
* <pre> |
|
238 |
* JMXConnector conn = JMXConnectorFactory.newJMXConnector(serviceURL, |
|
239 |
* environment); |
|
240 |
* conn.connect(environment); |
|
241 |
* </pre> |
|
242 |
* |
|
243 |
* @param serviceURL the address of the connector server to connect to. |
|
244 |
* |
|
245 |
* @param environment a set of attributes to determine how the |
|
246 |
* connection is made. This parameter can be null. Keys in this |
|
247 |
* map must be Strings. The appropriate type of each associated |
|
248 |
* value depends on the attribute. The contents of |
|
249 |
* <code>environment</code> are not changed by this call. |
|
250 |
* |
|
251 |
* @return a <code>JMXConnector</code> representing the newly-made |
|
252 |
* connection. Each successful call to this method produces a |
|
253 |
* different object. |
|
254 |
* |
|
255 |
* @exception NullPointerException if <code>serviceURL</code> is null. |
|
256 |
* |
|
257 |
* @exception IOException if the connector client or the |
|
258 |
* connection cannot be made because of a communication problem. |
|
259 |
* |
|
260 |
* @exception SecurityException if the connection cannot be made |
|
261 |
* for security reasons. |
|
262 |
*/ |
|
263 |
public static JMXConnector connect(JMXServiceURL serviceURL, |
|
264 |
Map<String,?> environment) |
|
265 |
throws IOException { |
|
266 |
if (serviceURL == null) |
|
267 |
throw new NullPointerException("Null JMXServiceURL"); |
|
268 |
JMXConnector conn = newJMXConnector(serviceURL, environment); |
|
269 |
conn.connect(environment); |
|
270 |
return conn; |
|
271 |
} |
|
272 |
||
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
273 |
private static <K,V> Map<K,V> newHashMap() { |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
274 |
return new HashMap<K,V>(); |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
275 |
} |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
276 |
|
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
277 |
private static <K> Map<K,Object> newHashMap(Map<K,?> map) { |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
278 |
return new HashMap<K,Object>(map); |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
279 |
} |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
280 |
|
2 | 281 |
/** |
282 |
* <p>Creates a connector client for the connector server at the |
|
283 |
* given address. The resultant client is not connected until its |
|
284 |
* {@link JMXConnector#connect(Map) connect} method is called.</p> |
|
285 |
* |
|
286 |
* @param serviceURL the address of the connector server to connect to. |
|
287 |
* |
|
288 |
* @param environment a set of attributes to determine how the |
|
289 |
* connection is made. This parameter can be null. Keys in this |
|
290 |
* map must be Strings. The appropriate type of each associated |
|
291 |
* value depends on the attribute. The contents of |
|
292 |
* <code>environment</code> are not changed by this call. |
|
293 |
* |
|
294 |
* @return a <code>JMXConnector</code> representing the new |
|
295 |
* connector client. Each successful call to this method produces |
|
296 |
* a different object. |
|
297 |
* |
|
298 |
* @exception NullPointerException if <code>serviceURL</code> is null. |
|
299 |
* |
|
300 |
* @exception IOException if the connector client cannot be made |
|
301 |
* because of a communication problem. |
|
302 |
* |
|
303 |
* @exception MalformedURLException if there is no provider for the |
|
304 |
* protocol in <code>serviceURL</code>. |
|
305 |
* |
|
306 |
* @exception JMXProviderException if there is a provider for the |
|
307 |
* protocol in <code>serviceURL</code> but it cannot be used for |
|
308 |
* some reason. |
|
309 |
*/ |
|
310 |
public static JMXConnector newJMXConnector(JMXServiceURL serviceURL, |
|
311 |
Map<String,?> environment) |
|
312 |
throws IOException { |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
313 |
|
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
314 |
final Map<String,Object> envcopy; |
2 | 315 |
if (environment == null) |
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
316 |
envcopy = newHashMap(); |
2 | 317 |
else { |
318 |
EnvHelp.checkAttributes(environment); |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
319 |
envcopy = newHashMap(environment); |
2 | 320 |
} |
321 |
||
322 |
final ClassLoader loader = resolveClassLoader(envcopy); |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
323 |
final Class<JMXConnectorProvider> targetInterface = |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
324 |
JMXConnectorProvider.class; |
2 | 325 |
final String protocol = serviceURL.getProtocol(); |
326 |
final String providerClassName = "ClientProvider"; |
|
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
327 |
final JMXServiceURL providerURL = serviceURL; |
2 | 328 |
|
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
329 |
JMXConnectorProvider provider = getProvider(providerURL, envcopy, |
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
330 |
providerClassName, |
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
331 |
targetInterface, |
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
332 |
loader); |
2 | 333 |
|
334 |
IOException exception = null; |
|
335 |
if (provider == null) { |
|
336 |
// Loader is null when context class loader is set to null |
|
337 |
// and no loader has been provided in map. |
|
338 |
// com.sun.jmx.remote.util.Service class extracted from j2se |
|
339 |
// provider search algorithm doesn't handle well null classloader. |
|
340 |
if (loader != null) { |
|
341 |
try { |
|
342 |
JMXConnector connection = |
|
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
343 |
getConnectorAsService(loader, providerURL, envcopy); |
2 | 344 |
if (connection != null) |
345 |
return connection; |
|
346 |
} catch (JMXProviderException e) { |
|
347 |
throw e; |
|
348 |
} catch (IOException e) { |
|
349 |
exception = e; |
|
350 |
} |
|
351 |
} |
|
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
352 |
provider = getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE, |
2 | 353 |
JMXConnectorFactory.class.getClassLoader(), |
354 |
providerClassName, targetInterface); |
|
355 |
} |
|
356 |
||
357 |
if (provider == null) { |
|
358 |
MalformedURLException e = |
|
359 |
new MalformedURLException("Unsupported protocol: " + protocol); |
|
360 |
if (exception == null) { |
|
361 |
throw e; |
|
362 |
} else { |
|
363 |
throw EnvHelp.initCause(e, exception); |
|
364 |
} |
|
365 |
} |
|
366 |
||
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
367 |
final Map<String,Object> fixedenv = |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
368 |
Collections.unmodifiableMap(envcopy); |
2 | 369 |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
370 |
return provider.newJMXConnector(serviceURL, fixedenv); |
2 | 371 |
} |
372 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1156
diff
changeset
|
373 |
private static String resolvePkgs(Map<String, ?> env) |
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1156
diff
changeset
|
374 |
throws JMXProviderException { |
2 | 375 |
|
376 |
Object pkgsObject = null; |
|
377 |
||
378 |
if (env != null) |
|
379 |
pkgsObject = env.get(PROTOCOL_PROVIDER_PACKAGES); |
|
380 |
||
381 |
if (pkgsObject == null) |
|
382 |
pkgsObject = |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
383 |
AccessController.doPrivileged(new PrivilegedAction<String>() { |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
384 |
public String run() { |
2 | 385 |
return System.getProperty(PROTOCOL_PROVIDER_PACKAGES); |
386 |
} |
|
387 |
}); |
|
388 |
||
389 |
if (pkgsObject == null) |
|
390 |
return null; |
|
391 |
||
392 |
if (!(pkgsObject instanceof String)) { |
|
393 |
final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES + |
|
394 |
" parameter is not a String: " + |
|
395 |
pkgsObject.getClass().getName(); |
|
396 |
throw new JMXProviderException(msg); |
|
397 |
} |
|
398 |
||
399 |
final String pkgs = (String) pkgsObject; |
|
400 |
if (pkgs.trim().equals("")) |
|
401 |
return null; |
|
402 |
||
403 |
// pkgs may not contain an empty element |
|
404 |
if (pkgs.startsWith("|") || pkgs.endsWith("|") || |
|
405 |
pkgs.indexOf("||") >= 0) { |
|
406 |
final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES + |
|
407 |
" contains an empty element: " + pkgs; |
|
408 |
throw new JMXProviderException(msg); |
|
409 |
} |
|
410 |
||
411 |
return pkgs; |
|
412 |
} |
|
413 |
||
414 |
static <T> T getProvider(JMXServiceURL serviceURL, |
|
415 |
Map<String, Object> environment, |
|
416 |
String providerClassName, |
|
417 |
Class<T> targetInterface, |
|
418 |
ClassLoader loader) |
|
419 |
throws IOException { |
|
420 |
||
421 |
final String protocol = serviceURL.getProtocol(); |
|
422 |
||
423 |
final String pkgs = resolvePkgs(environment); |
|
424 |
||
425 |
T instance = null; |
|
426 |
||
427 |
if (pkgs != null) { |
|
428 |
environment.put(PROTOCOL_PROVIDER_CLASS_LOADER, loader); |
|
429 |
||
430 |
instance = |
|
431 |
getProvider(protocol, pkgs, loader, providerClassName, |
|
432 |
targetInterface); |
|
433 |
} |
|
434 |
||
435 |
return instance; |
|
436 |
} |
|
437 |
||
438 |
static <T> Iterator<T> getProviderIterator(final Class<T> providerClass, |
|
439 |
final ClassLoader loader) { |
|
440 |
ServiceLoader<T> serviceLoader = |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
441 |
ServiceLoader.load(providerClass, loader); |
2 | 442 |
return serviceLoader.iterator(); |
443 |
} |
|
444 |
||
445 |
private static JMXConnector getConnectorAsService(ClassLoader loader, |
|
446 |
JMXServiceURL url, |
|
447 |
Map<String, ?> map) |
|
448 |
throws IOException { |
|
449 |
||
450 |
Iterator<JMXConnectorProvider> providers = |
|
451 |
getProviderIterator(JMXConnectorProvider.class, loader); |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
452 |
JMXConnector connection; |
2 | 453 |
IOException exception = null; |
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
454 |
while (providers.hasNext()) { |
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
455 |
JMXConnectorProvider provider = providers.next(); |
2 | 456 |
try { |
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
457 |
connection = provider.newJMXConnector(url, map); |
2 | 458 |
return connection; |
459 |
} catch (JMXProviderException e) { |
|
460 |
throw e; |
|
461 |
} catch (Exception e) { |
|
462 |
if (logger.traceOn()) |
|
463 |
logger.trace("getConnectorAsService", |
|
464 |
"URL[" + url + |
|
465 |
"] Service provider exception: " + e); |
|
466 |
if (!(e instanceof MalformedURLException)) { |
|
467 |
if (exception == null) { |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
468 |
if (e instanceof IOException) { |
2 | 469 |
exception = (IOException) e; |
470 |
} else { |
|
471 |
exception = EnvHelp.initCause( |
|
472 |
new IOException(e.getMessage()), e); |
|
473 |
} |
|
474 |
} |
|
475 |
} |
|
476 |
continue; |
|
477 |
} |
|
478 |
} |
|
479 |
if (exception == null) |
|
480 |
return null; |
|
481 |
else |
|
482 |
throw exception; |
|
483 |
} |
|
484 |
||
485 |
static <T> T getProvider(String protocol, |
|
486 |
String pkgs, |
|
487 |
ClassLoader loader, |
|
488 |
String providerClassName, |
|
489 |
Class<T> targetInterface) |
|
490 |
throws IOException { |
|
491 |
||
492 |
StringTokenizer tokenizer = new StringTokenizer(pkgs, "|"); |
|
493 |
||
494 |
while (tokenizer.hasMoreTokens()) { |
|
495 |
String pkg = tokenizer.nextToken(); |
|
496 |
String className = (pkg + "." + protocol2package(protocol) + |
|
497 |
"." + providerClassName); |
|
498 |
Class<?> providerClass; |
|
499 |
try { |
|
500 |
providerClass = Class.forName(className, true, loader); |
|
501 |
} catch (ClassNotFoundException e) { |
|
502 |
//Add trace. |
|
503 |
continue; |
|
504 |
} |
|
505 |
||
506 |
if (!targetInterface.isAssignableFrom(providerClass)) { |
|
507 |
final String msg = |
|
508 |
"Provider class does not implement " + |
|
509 |
targetInterface.getName() + ": " + |
|
510 |
providerClass.getName(); |
|
511 |
throw new JMXProviderException(msg); |
|
512 |
} |
|
513 |
||
514 |
// We have just proved that this cast is correct |
|
515 |
Class<? extends T> providerClassT = Util.cast(providerClass); |
|
516 |
try { |
|
517 |
return providerClassT.newInstance(); |
|
518 |
} catch (Exception e) { |
|
519 |
final String msg = |
|
520 |
"Exception when instantiating provider [" + className + |
|
521 |
"]"; |
|
522 |
throw new JMXProviderException(msg, e); |
|
523 |
} |
|
524 |
} |
|
525 |
||
526 |
return null; |
|
527 |
} |
|
528 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1156
diff
changeset
|
529 |
static ClassLoader resolveClassLoader(Map<String, ?> environment) { |
2 | 530 |
ClassLoader loader = null; |
531 |
||
532 |
if (environment != null) { |
|
533 |
try { |
|
534 |
loader = (ClassLoader) |
|
535 |
environment.get(PROTOCOL_PROVIDER_CLASS_LOADER); |
|
536 |
} catch (ClassCastException e) { |
|
537 |
final String msg = |
|
538 |
"The ClassLoader supplied in the environment map using " + |
|
539 |
"the " + PROTOCOL_PROVIDER_CLASS_LOADER + |
|
540 |
" attribute is not an instance of java.lang.ClassLoader"; |
|
541 |
throw new IllegalArgumentException(msg); |
|
542 |
} |
|
543 |
} |
|
544 |
||
545 |
if (loader == null) |
|
1156
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
546 |
loader = AccessController.doPrivileged( |
bbc2d15aaf7a
5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents:
715
diff
changeset
|
547 |
new PrivilegedAction<ClassLoader>() { |
2 | 548 |
public ClassLoader run() { |
549 |
return |
|
550 |
Thread.currentThread().getContextClassLoader(); |
|
551 |
} |
|
552 |
}); |
|
553 |
||
554 |
return loader; |
|
555 |
} |
|
556 |
||
557 |
private static String protocol2package(String protocol) { |
|
558 |
return protocol.replace('+', '.').replace('-', '_'); |
|
559 |
} |
|
1570
4165709c91e3
5072267: A way to communicate client context such as locale to the JMX server
emcmanus
parents:
1510
diff
changeset
|
560 |
|
2 | 561 |
} |