Source Code Cross Referenced for JMXConnectorFactory.java in  » 6.0-JDK-Core » management » javax » management » remote » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » management » javax.management.remote 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package javax.management.remote;
027
028        import com.sun.jmx.mbeanserver.Util;
029        import java.io.IOException;
030        import java.net.MalformedURLException;
031        import java.util.Collections;
032        import java.util.HashMap;
033        import java.util.Map;
034        import java.util.Iterator;
035        import java.util.ServiceLoader;
036        import java.util.StringTokenizer;
037        import java.security.AccessController;
038        import java.security.PrivilegedAction;
039
040        import com.sun.jmx.remote.util.ClassLogger;
041        import com.sun.jmx.remote.util.EnvHelp;
042
043        /**
044         * <p>Factory to create JMX API connector clients.  There
045         * are no instances of this class.</p>
046         *
047         * <p>Connections are usually made using the {@link
048         * #connect(JMXServiceURL) connect} method of this class.  More
049         * advanced applications can separate the creation of the connector
050         * client, using {@link #newJMXConnector(JMXServiceURL, Map)
051         * newJMXConnector} and the establishment of the connection itself, using
052         * {@link JMXConnector#connect(Map)}.</p>
053         *
054         * <p>Each client is created by an instance of {@link
055         * JMXConnectorProvider}.  This instance is found as follows.  Suppose
056         * the given {@link JMXServiceURL} looks like
057         * <code>"service:jmx:<em>protocol</em>:<em>remainder</em>"</code>.
058         * Then the factory will attempt to find the appropriate {@link
059         * JMXConnectorProvider} for <code><em>protocol</em></code>.  Each
060         * occurrence of the character <code>+</code> or <code>-</code> in
061         * <code><em>protocol</em></code> is replaced by <code>.</code> or
062         * <code>_</code>, respectively.</p>
063         *
064         * <p>A <em>provider package list</em> is searched for as follows:</p>
065         *
066         * <ol>
067         *
068         * <li>If the <code>environment</code> parameter to {@link
069         * #newJMXConnector(JMXServiceURL, Map) newJMXConnector} contains the
070         * key <code>jmx.remote.protocol.provider.pkgs</code> then the
071         * associated value is the provider package list.
072         *
073         * <li>Otherwise, if the system property
074         * <code>jmx.remote.protocol.provider.pkgs</code> exists, then its value
075         * is the provider package list.
076         *
077         * <li>Otherwise, there is no provider package list.
078         *
079         * </ol>
080         *
081         * <p>The provider package list is a string that is interpreted as a
082         * list of non-empty Java package names separated by vertical bars
083         * (<code>|</code>).  If the string is empty, then so is the provider
084         * package list.  If the provider package list is not a String, or if
085         * it contains an element that is an empty string, a {@link
086         * JMXProviderException} is thrown.</p>
087         *
088         * <p>If the provider package list exists and is not empty, then for
089         * each element <code><em>pkg</em></code> of the list, the factory
090         * will attempt to load the class
091         *
092         * <blockquote>
093         * <code><em>pkg</em>.<em>protocol</em>.ClientProvider</code>
094         * </blockquote>
095
096         * <p>If the <code>environment</code> parameter to {@link
097         * #newJMXConnector(JMXServiceURL, Map) newJMXConnector} contains the
098         * key <code>jmx.remote.protocol.provider.class.loader</code> then the
099         * associated value is the class loader to use to load the provider.
100         * If the associated value is not an instance of {@link
101         * java.lang.ClassLoader}, an {@link
102         * java.lang.IllegalArgumentException} is thrown.</p>
103         *
104         * <p>If the <code>jmx.remote.protocol.provider.class.loader</code>
105         * key is not present in the <code>environment</code> parameter, the
106         * calling thread's context class loader is used.</p>
107         *
108         * <p>If the attempt to load this class produces a {@link
109         * ClassNotFoundException}, the search for a handler continues with
110         * the next element of the list.</p>
111         *
112         * <p>Otherwise, a problem with the provider found is signalled by a
113         * {@link JMXProviderException} whose {@link
114         * JMXProviderException#getCause() <em>cause</em>} indicates the underlying
115         * exception, as follows:</p>
116         *
117         * <ul>
118         *
119         * <li>if the attempt to load the class produces an exception other
120         * than <code>ClassNotFoundException</code>, that is the
121         * <em>cause</em>;
122         *
123         * <li>if {@link Class#newInstance()} for the class produces an
124         * exception, that is the <em>cause</em>.
125         *
126         * </ul>
127         *
128         * <p>If no provider is found by the above steps, including the
129         * default case where there is no provider package list, then the
130         * implementation will use its own provider for
131         * <code><em>protocol</em></code>, or it will throw a
132         * <code>MalformedURLException</code> if there is none.  An
133         * implementation may choose to find providers by other means.  For
134         * example, it may support the <a
135         * href="{@docRoot}/../technotes/guides/jar/jar.html#Service Provider">
136         * JAR conventions for service providers</a>, where the service
137         * interface is <code>JMXConnectorProvider</code>.</p>
138         *
139         * <p>Every implementation must support the RMI connector protocols,
140         * specified with the string <code>rmi</code> or
141         * <code>iiop</code>.</p>
142         *
143         * <p>Once a provider is found, the result of the
144         * <code>newJMXConnector</code> method is the result of calling {@link
145         * JMXConnectorProvider#newJMXConnector(JMXServiceURL,Map) newJMXConnector}
146         * on the provider.</p>
147         *
148         * <p>The <code>Map</code> parameter passed to the
149         * <code>JMXConnectorProvider</code> is a new read-only
150         * <code>Map</code> that contains all the entries that were in the
151         * <code>environment</code> parameter to {@link
152         * #newJMXConnector(JMXServiceURL,Map)
153         * JMXConnectorFactory.newJMXConnector}, if there was one.
154         * Additionally, if the
155         * <code>jmx.remote.protocol.provider.class.loader</code> key is not
156         * present in the <code>environment</code> parameter, it is added to
157         * the new read-only <code>Map</code>.  The associated value is the
158         * calling thread's context class loader.</p>
159         *
160         * @since 1.5
161         */
162        public class JMXConnectorFactory {
163
164            /**
165             * <p>Name of the attribute that specifies the default class
166             * loader. This class loader is used to deserialize return values and
167             * exceptions from remote <code>MBeanServerConnection</code>
168             * calls.  The value associated with this attribute is an instance
169             * of {@link ClassLoader}.</p>
170             */
171            public static final String DEFAULT_CLASS_LOADER = "jmx.remote.default.class.loader";
172
173            /**
174             * <p>Name of the attribute that specifies the provider packages
175             * that are consulted when looking for the handler for a protocol.
176             * The value associated with this attribute is a string with
177             * package names separated by vertical bars (<code>|</code>).</p>
178             */
179            public static final String PROTOCOL_PROVIDER_PACKAGES = "jmx.remote.protocol.provider.pkgs";
180
181            /**
182             * <p>Name of the attribute that specifies the class
183             * loader for loading protocol providers.
184             * The value associated with this attribute is an instance
185             * of {@link ClassLoader}.</p>
186             */
187            public static final String PROTOCOL_PROVIDER_CLASS_LOADER = "jmx.remote.protocol.provider.class.loader";
188
189            private static final String PROTOCOL_PROVIDER_DEFAULT_PACKAGE = "com.sun.jmx.remote.protocol";
190
191            private static final ClassLogger logger = new ClassLogger(
192                    "javax.management.remote.misc", "JMXConnectorFactory");
193
194            /** There are no instances of this class.  */
195            private JMXConnectorFactory() {
196            }
197
198            /**
199             * <p>Creates a connection to the connector server at the given
200             * address.</p>
201             *
202             * <p>This method is equivalent to {@link
203             * #connect(JMXServiceURL,Map) connect(serviceURL, null)}.</p>
204             *
205             * @param serviceURL the address of the connector server to
206             * connect to.
207             *
208             * @return a <code>JMXConnector</code> whose {@link
209             * JMXConnector#connect connect} method has been called.
210             *
211             * @exception NullPointerException if <code>serviceURL</code> is null.
212             *
213             * @exception IOException if the connector client or the
214             * connection cannot be made because of a communication problem.
215             *
216             * @exception SecurityException if the connection cannot be made
217             * for security reasons.
218             */
219            public static JMXConnector connect(JMXServiceURL serviceURL)
220                    throws IOException {
221                return connect(serviceURL, null);
222            }
223
224            /**
225             * <p>Creates a connection to the connector server at the given
226             * address.</p>
227             *
228             * <p>This method is equivalent to:</p>
229             *
230             * <pre>
231             * JMXConnector conn = JMXConnectorFactory.newJMXConnector(serviceURL,
232             *                                                         environment);
233             * conn.connect(environment);
234             * </pre>
235             *
236             * @param serviceURL the address of the connector server to connect to.
237             *
238             * @param environment a set of attributes to determine how the
239             * connection is made.  This parameter can be null.  Keys in this
240             * map must be Strings.  The appropriate type of each associated
241             * value depends on the attribute.  The contents of
242             * <code>environment</code> are not changed by this call.
243             *
244             * @return a <code>JMXConnector</code> representing the newly-made
245             * connection.  Each successful call to this method produces a
246             * different object.
247             *
248             * @exception NullPointerException if <code>serviceURL</code> is null.
249             *
250             * @exception IOException if the connector client or the
251             * connection cannot be made because of a communication problem.
252             *
253             * @exception SecurityException if the connection cannot be made
254             * for security reasons.
255             */
256            public static JMXConnector connect(JMXServiceURL serviceURL,
257                    Map<String, ?> environment) throws IOException {
258                if (serviceURL == null)
259                    throw new NullPointerException("Null JMXServiceURL");
260                JMXConnector conn = newJMXConnector(serviceURL, environment);
261                conn.connect(environment);
262                return conn;
263            }
264
265            /**
266             * <p>Creates a connector client for the connector server at the
267             * given address.  The resultant client is not connected until its
268             * {@link JMXConnector#connect(Map) connect} method is called.</p>
269             *
270             * @param serviceURL the address of the connector server to connect to.
271             *
272             * @param environment a set of attributes to determine how the
273             * connection is made.  This parameter can be null.  Keys in this
274             * map must be Strings.  The appropriate type of each associated
275             * value depends on the attribute.  The contents of
276             * <code>environment</code> are not changed by this call.
277             *
278             * @return a <code>JMXConnector</code> representing the new
279             * connector client.  Each successful call to this method produces
280             * a different object.
281             *
282             * @exception NullPointerException if <code>serviceURL</code> is null.
283             *
284             * @exception IOException if the connector client cannot be made
285             * because of a communication problem.
286             *
287             * @exception MalformedURLException if there is no provider for the
288             * protocol in <code>serviceURL</code>.
289             *
290             * @exception JMXProviderException if there is a provider for the
291             * protocol in <code>serviceURL</code> but it cannot be used for
292             * some reason.
293             */
294            public static JMXConnector newJMXConnector(
295                    JMXServiceURL serviceURL, Map<String, ?> environment)
296                    throws IOException {
297                Map<String, Object> envcopy;
298                if (environment == null)
299                    envcopy = new HashMap<String, Object>();
300                else {
301                    EnvHelp.checkAttributes(environment);
302                    envcopy = new HashMap<String, Object>(environment);
303                }
304
305                final ClassLoader loader = resolveClassLoader(envcopy);
306                final Class<JMXConnectorProvider> targetInterface = JMXConnectorProvider.class;
307                final String protocol = serviceURL.getProtocol();
308                final String providerClassName = "ClientProvider";
309
310                JMXConnectorProvider provider = getProvider(serviceURL,
311                        envcopy, providerClassName, targetInterface, loader);
312
313                IOException exception = null;
314                if (provider == null) {
315                    // Loader is null when context class loader is set to null
316                    // and no loader has been provided in map.
317                    // com.sun.jmx.remote.util.Service class extracted from j2se
318                    // provider search algorithm doesn't handle well null classloader.
319                    if (loader != null) {
320                        try {
321                            JMXConnector connection = getConnectorAsService(
322                                    loader, serviceURL, envcopy);
323                            if (connection != null)
324                                return connection;
325                        } catch (JMXProviderException e) {
326                            throw e;
327                        } catch (IOException e) {
328                            exception = e;
329                        }
330                    }
331                    provider = getProvider(protocol,
332                            PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
333                            JMXConnectorFactory.class.getClassLoader(),
334                            providerClassName, targetInterface);
335                }
336
337                if (provider == null) {
338                    MalformedURLException e = new MalformedURLException(
339                            "Unsupported protocol: " + protocol);
340                    if (exception == null) {
341                        throw e;
342                    } else {
343                        throw EnvHelp.initCause(e, exception);
344                    }
345                }
346
347                envcopy = Collections.unmodifiableMap(envcopy);
348
349                return provider.newJMXConnector(serviceURL, envcopy);
350            }
351
352            private static String resolvePkgs(Map env)
353                    throws JMXProviderException {
354
355                Object pkgsObject = null;
356
357                if (env != null)
358                    pkgsObject = env.get(PROTOCOL_PROVIDER_PACKAGES);
359
360                if (pkgsObject == null)
361                    pkgsObject = AccessController
362                            .doPrivileged(new PrivilegedAction<Object>() {
363                                public Object run() {
364                                    return System
365                                            .getProperty(PROTOCOL_PROVIDER_PACKAGES);
366                                }
367                            });
368
369                if (pkgsObject == null)
370                    return null;
371
372                if (!(pkgsObject instanceof  String)) {
373                    final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES
374                            + " parameter is not a String: "
375                            + pkgsObject.getClass().getName();
376                    throw new JMXProviderException(msg);
377                }
378
379                final String pkgs = (String) pkgsObject;
380                if (pkgs.trim().equals(""))
381                    return null;
382
383                // pkgs may not contain an empty element
384                if (pkgs.startsWith("|") || pkgs.endsWith("|")
385                        || pkgs.indexOf("||") >= 0) {
386                    final String msg = "Value of " + PROTOCOL_PROVIDER_PACKAGES
387                            + " contains an empty element: " + pkgs;
388                    throw new JMXProviderException(msg);
389                }
390
391                return pkgs;
392            }
393
394            static <T> T getProvider(JMXServiceURL serviceURL,
395                    Map<String, Object> environment, String providerClassName,
396                    Class<T> targetInterface, ClassLoader loader)
397                    throws IOException {
398
399                final String protocol = serviceURL.getProtocol();
400
401                final String pkgs = resolvePkgs(environment);
402
403                T instance = null;
404
405                if (pkgs != null) {
406                    environment.put(PROTOCOL_PROVIDER_CLASS_LOADER, loader);
407
408                    instance = getProvider(protocol, pkgs, loader,
409                            providerClassName, targetInterface);
410                }
411
412                return instance;
413            }
414
415            static <T> Iterator<T> getProviderIterator(
416                    final Class<T> providerClass, final ClassLoader loader) {
417                ServiceLoader<T> serviceLoader = ServiceLoader.load(
418                        providerClass, loader);
419                return serviceLoader.iterator();
420            }
421
422            private static JMXConnector getConnectorAsService(
423                    ClassLoader loader, JMXServiceURL url, Map<String, ?> map)
424                    throws IOException {
425
426                Iterator<JMXConnectorProvider> providers = getProviderIterator(
427                        JMXConnectorProvider.class, loader);
428                JMXConnector connection = null;
429                IOException exception = null;
430                while (providers.hasNext()) {
431                    try {
432                        connection = providers.next().newJMXConnector(url, map);
433                        return connection;
434                    } catch (JMXProviderException e) {
435                        throw e;
436                    } catch (Exception e) {
437                        if (logger.traceOn())
438                            logger.trace("getConnectorAsService", "URL[" + url
439                                    + "] Service provider exception: " + e);
440                        if (!(e instanceof  MalformedURLException)) {
441                            if (exception == null) {
442                                if (exception instanceof  IOException) {
443                                    exception = (IOException) e;
444                                } else {
445                                    exception = EnvHelp.initCause(
446                                            new IOException(e.getMessage()), e);
447                                }
448                            }
449                        }
450                        continue;
451                    }
452                }
453                if (exception == null)
454                    return null;
455                else
456                    throw exception;
457            }
458
459            static <T> T getProvider(String protocol, String pkgs,
460                    ClassLoader loader, String providerClassName,
461                    Class<T> targetInterface) throws IOException {
462
463                StringTokenizer tokenizer = new StringTokenizer(pkgs, "|");
464
465                while (tokenizer.hasMoreTokens()) {
466                    String pkg = tokenizer.nextToken();
467                    String className = (pkg + "." + protocol2package(protocol)
468                            + "." + providerClassName);
469                    Class<?> providerClass;
470                    try {
471                        providerClass = Class.forName(className, true, loader);
472                    } catch (ClassNotFoundException e) {
473                        //Add trace.
474                        continue;
475                    }
476
477                    if (!targetInterface.isAssignableFrom(providerClass)) {
478                        final String msg = "Provider class does not implement "
479                                + targetInterface.getName() + ": "
480                                + providerClass.getName();
481                        throw new JMXProviderException(msg);
482                    }
483
484                    // We have just proved that this cast is correct
485                    Class<? extends T> providerClassT = Util
486                            .cast(providerClass);
487                    try {
488                        return providerClassT.newInstance();
489                    } catch (Exception e) {
490                        final String msg = "Exception when instantiating provider ["
491                                + className + "]";
492                        throw new JMXProviderException(msg, e);
493                    }
494                }
495
496                return null;
497            }
498
499            static ClassLoader resolveClassLoader(Map environment) {
500                ClassLoader loader = null;
501
502                if (environment != null) {
503                    try {
504                        loader = (ClassLoader) environment
505                                .get(PROTOCOL_PROVIDER_CLASS_LOADER);
506                    } catch (ClassCastException e) {
507                        final String msg = "The ClassLoader supplied in the environment map using "
508                                + "the "
509                                + PROTOCOL_PROVIDER_CLASS_LOADER
510                                + " attribute is not an instance of java.lang.ClassLoader";
511                        throw new IllegalArgumentException(msg);
512                    }
513                }
514
515                if (loader == null)
516                    loader = AccessController
517                            .doPrivileged(new PrivilegedAction<ClassLoader>() {
518                                public ClassLoader run() {
519                                    return Thread.currentThread()
520                                            .getContextClassLoader();
521                                }
522                            });
523
524                return loader;
525            }
526
527            private static String protocol2package(String protocol) {
528                return protocol.replace('+', '.').replace('-', '_');
529            }
530        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.