1336 lines · 54.7 KB · Java
RawDownload
/* * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.management.loading; // Java importimport com.sun.jmx.defaults.JmxProperties; import com.sun.jmx.defaults.ServiceName; import com.sun.jmx.remote.util.EnvHelp; import java.io.Externalizable;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInput;import java.io.ObjectInputStream;import java.io.ObjectOutput;import java.lang.reflect.Constructor;import java.net.MalformedURLException;import java.net.URL;import java.net.URLStreamHandlerFactory;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.logging.Level;import java.util.Map;import java.util.Set;import java.util.StringTokenizer; import javax.management.InstanceAlreadyExistsException;import javax.management.InstanceNotFoundException;import javax.management.MBeanException;import javax.management.MBeanRegistration;import javax.management.MBeanRegistrationException;import javax.management.MBeanServer;import javax.management.NotCompliantMBeanException;import javax.management.ObjectInstance;import javax.management.ObjectName;import javax.management.ReflectionException; import static com.sun.jmx.defaults.JmxProperties.MLET_LIB_DIR;import static com.sun.jmx.defaults.JmxProperties.MLET_LOGGER;import com.sun.jmx.defaults.ServiceName;import javax.management.ServiceNotFoundException; /** * Allows you to instantiate and register one or several MBeans in the MBean server * coming from a remote URL. M-let is a shortcut for management applet. The m-let service does this * by loading an m-let text file, which specifies information on the MBeans to be obtained. * The information on each MBean is specified in a single instance of a tag, called the MLET tag. * The location of the m-let text file is specified by a URL. * <p> * The <CODE>MLET</CODE> tag has the following syntax: * <p> * &lt;<CODE>MLET</CODE><BR> *      <CODE>CODE = </CODE><VAR>class</VAR><CODE> | OBJECT = </CODE><VAR>serfile</VAR><BR> *      <CODE>ARCHIVE = &quot;</CODE><VAR>archiveList</VAR><CODE>&quot;</CODE><BR> *      <CODE>[CODEBASE = </CODE><VAR>codebaseURL</VAR><CODE>]</CODE><BR> *      <CODE>[NAME = </CODE><VAR>mbeanname</VAR><CODE>]</CODE><BR> *      <CODE>[VERSION = </CODE><VAR>version</VAR><CODE>]</CODE><BR> * &gt;<BR> *      <CODE>[</CODE><VAR>arglist</VAR><CODE>]</CODE><BR> * &lt;<CODE>/MLET</CODE>&gt; * <p> * where: * <DL> * <DT><CODE>CODE = </CODE><VAR>class</VAR></DT> * <DD> * This attribute specifies the full Java class name, including package name, of the MBean to be obtained. * The compiled <CODE>.class</CODE> file of the MBean must be contained in one of the <CODE>.jar</CODE> files specified by the <CODE>ARCHIVE</CODE> * attribute. Either <CODE>CODE</CODE> or <CODE>OBJECT</CODE> must be present. * </DD> * <DT><CODE>OBJECT = </CODE><VAR>serfile</VAR></DT> * <DD> * This attribute specifies the <CODE>.ser</CODE> file that contains a serialized representation of the MBean to be obtained. * This file must be contained in one of the <CODE>.jar</CODE> files specified by the <CODE>ARCHIVE</CODE> attribute. If the <CODE>.jar</CODE> file contains a directory hierarchy, specify the path of the file within this hierarchy. Otherwise  a match will not be found. Either <CODE>CODE</CODE> or <CODE>OBJECT</CODE> must be present. * </DD> * <DT><CODE>ARCHIVE = &quot;</CODE><VAR>archiveList</VAR><CODE>&quot;</CODE></DT> * <DD> * This mandatory attribute specifies one or more <CODE>.jar</CODE> files * containing MBeans or other resources used by * the MBean to be obtained. One of the <CODE>.jar</CODE> files must contain the file specified by the <CODE>CODE</CODE> or <CODE>OBJECT</CODE> attribute. * If archivelist contains more than one file: * <UL> * <LI>Each file must be separated from the one that follows it by a comma (,). * <LI><VAR>archivelist</VAR> must be enclosed in double quote marks. * </UL> * All <CODE>.jar</CODE> files in <VAR>archivelist</VAR> must be stored in the directory specified by the code base URL. * </DD> * <DT><CODE>CODEBASE = </CODE><VAR>codebaseURL</VAR></DT> * <DD> * This optional attribute specifies the code base URL of the MBean to be obtained. It identifies the directory that contains * the <CODE>.jar</CODE> files specified by the <CODE>ARCHIVE</CODE> attribute. Specify this attribute only if the <CODE>.jar</CODE> files are not in the same * directory as the m-let text file. If this attribute is not specified, the base URL of the m-let text file is used. * </DD> * <DT><CODE>NAME = </CODE><VAR>mbeanname</VAR></DT> * <DD> * This optional attribute specifies the object name to be assigned to the * MBean instance when the m-let service registers it. If * <VAR>mbeanname</VAR> starts with the colon character (:), the domain * part of the object name is the default domain of the MBean server, * as returned by {@link javax.management.MBeanServer#getDefaultDomain()}. * </DD> * <DT><CODE>VERSION = </CODE><VAR>version</VAR></DT> * <DD> * This optional attribute specifies the version number of the MBean and * associated <CODE>.jar</CODE> files to be obtained. This version number can * be used to specify that the <CODE>.jar</CODE> files are loaded from the * server to update those stored locally in the cache the next time the m-let * text file is loaded. <VAR>version</VAR> must be a series of non-negative * decimal integers each separated by a period from the one that precedes it. * </DD> * <DT><VAR>arglist</VAR></DT> * <DD> * This optional attribute specifies a list of one or more parameters for the * MBean to be instantiated. This list describes the parameters to be passed the MBean's constructor. * Use the following syntax to specify each item in * <VAR>arglist</VAR>:</DD> * <DL> * <P> * <DT>&lt;<CODE>ARG TYPE=</CODE><VAR>argumentType</VAR> <CODE>VALUE=</CODE><VAR>value</VAR>&gt;</DT> * <P> * <DD>where:</DD> * <UL> * <LI><VAR>argumentType</VAR> is the type of the argument that will be passed as parameter to the MBean's constructor.</UL> * </DL> * <P>The arguments' type in the argument list should be a Java primitive type or a Java basic type * (<CODE>java.lang.Boolean, java.lang.Byte, java.lang.Short, java.lang.Long, java.lang.Integer, java.lang.Float, java.lang.Double, java.lang.String</CODE>). * </DL> * * When an m-let text file is loaded, an * instance of each MBean specified in the file is created and registered. * <P> * The m-let service extends the <CODE>java.net.URLClassLoader</CODE> and can be used to load remote classes * and jar files in the VM of the agent. * <p><STRONG>Note - </STRONG> The <CODE>MLet</CODE> class loader uses the {@link javax.management.MBeanServerFactory#getClassLoaderRepository(javax.management.MBeanServer)} * to load classes that could not be found in the loaded jar files. * * @since 1.5 */public class MLet extends java.net.URLClassLoader     implements MLetMBean, MBeanRegistration, Externalizable {      private static final long serialVersionUID = 3636148327800330130L;      /*     * ------------------------------------------     *   PRIVATE VARIABLES     * ------------------------------------------     */      /**      * The reference to the MBean server.      * @serial      */     private MBeanServer server = null;       /**      * The list of instances of the <CODE>MLetContent</CODE>      * class found at the specified URL.      * @serial      */     private List<MLetContent> mletList = new ArrayList<MLetContent>();       /**      * The directory used for storing libraries locally before they are loaded.      */     private String libraryDirectory;       /**      * The object name of the MLet Service.      * @serial      */     private ObjectName mletObjectName = null;      /**      * The URLs of the MLet Service.      * @serial      */     private URL[] myUrls = null;      /**      * What ClassLoaderRepository, if any, to use if this MLet      * doesn't find an asked-for class.      */     private transient ClassLoaderRepository currentClr;      /**      * True if we should consult the {@link ClassLoaderRepository}      * when we do not find a class ourselves.      */     private transient boolean delegateToCLR;      /**      * objects maps from primitive classes to primitive object classes.      */     private Map<String,Class<?>> primitiveClasses =         new HashMap<String,Class<?>>(8) ;     {         primitiveClasses.put(Boolean.TYPE.toString(), Boolean.class);         primitiveClasses.put(Character.TYPE.toString(), Character.class);         primitiveClasses.put(Byte.TYPE.toString(), Byte.class);         primitiveClasses.put(Short.TYPE.toString(), Short.class);         primitiveClasses.put(Integer.TYPE.toString(), Integer.class);         primitiveClasses.put(Long.TYPE.toString(), Long.class);         primitiveClasses.put(Float.TYPE.toString(), Float.class);         primitiveClasses.put(Double.TYPE.toString(), Double.class);      }       /*      * ------------------------------------------      *  CONSTRUCTORS      * ------------------------------------------      */      /*      * The constructor stuff would be considerably simplified if our      * parent, URLClassLoader, specified that its one- and      * two-argument constructors were equivalent to its      * three-argument constructor with trailing null arguments.  But      * it doesn't, which prevents us from having all the constructors      * but one call this(...args...).      */      /**      * Constructs a new MLet using the default delegation parent ClassLoader.      */     public MLet() {         this(new URL[0]);     }      /**      * Constructs a new MLet for the specified URLs using the default      * delegation parent ClassLoader.  The URLs will be searched in      * the order specified for classes and resources after first      * searching in the parent class loader.      *      * @param  urls  The URLs from which to load classes and resources.      *      */     public MLet(URL[] urls) {         this(urls, true);     }      /**      * Constructs a new MLet for the given URLs. The URLs will be      * searched in the order specified for classes and resources      * after first searching in the specified parent class loader.      * The parent argument will be used as the parent class loader      * for delegation.      *      * @param  urls  The URLs from which to load classes and resources.      * @param  parent The parent class loader for delegation.      *      */     public MLet(URL[] urls, ClassLoader parent) {         this(urls, parent, true);     }      /**      * Constructs a new MLet for the specified URLs, parent class      * loader, and URLStreamHandlerFactory. The parent argument will      * be used as the parent class loader for delegation. The factory      * argument will be used as the stream handler factory to obtain      * protocol handlers when creating new URLs.      *      * @param  urls  The URLs from which to load classes and resources.      * @param  parent The parent class loader for delegation.      * @param  factory  The URLStreamHandlerFactory to use when creating URLs.      *      */     public MLet(URL[] urls,                 ClassLoader parent,                 URLStreamHandlerFactory factory) {         this(urls, parent, factory, true);     }      /**      * Constructs a new MLet for the specified URLs using the default      * delegation parent ClassLoader.  The URLs will be searched in      * the order specified for classes and resources after first      * searching in the parent class loader.      *      * @param  urls  The URLs from which to load classes and resources.      * @param  delegateToCLR  True if, when a class is not found in      * either the parent ClassLoader or the URLs, the MLet should delegate      * to its containing MBeanServer's {@link ClassLoaderRepository}.      *      */     public MLet(URL[] urls, boolean delegateToCLR) {         super(urls);         init(delegateToCLR);     }      /**      * Constructs a new MLet for the given URLs. The URLs will be      * searched in the order specified for classes and resources      * after first searching in the specified parent class loader.      * The parent argument will be used as the parent class loader      * for delegation.      *      * @param  urls  The URLs from which to load classes and resources.      * @param  parent The parent class loader for delegation.      * @param  delegateToCLR  True if, when a class is not found in      * either the parent ClassLoader or the URLs, the MLet should delegate      * to its containing MBeanServer's {@link ClassLoaderRepository}.      *      */     public MLet(URL[] urls, ClassLoader parent, boolean delegateToCLR) {         super(urls, parent);         init(delegateToCLR);     }      /**      * Constructs a new MLet for the specified URLs, parent class      * loader, and URLStreamHandlerFactory. The parent argument will      * be used as the parent class loader for delegation. The factory      * argument will be used as the stream handler factory to obtain      * protocol handlers when creating new URLs.      *      * @param  urls  The URLs from which to load classes and resources.      * @param  parent The parent class loader for delegation.      * @param  factory  The URLStreamHandlerFactory to use when creating URLs.      * @param  delegateToCLR  True if, when a class is not found in      * either the parent ClassLoader or the URLs, the MLet should delegate      * to its containing MBeanServer's {@link ClassLoaderRepository}.      *      */     public MLet(URL[] urls,                 ClassLoader parent,                 URLStreamHandlerFactory factory,                 boolean delegateToCLR) {         super(urls, parent, factory);         init(delegateToCLR);     }      private void init(boolean delegateToCLR) {         this.delegateToCLR = delegateToCLR;          try {             libraryDirectory = System.getProperty(MLET_LIB_DIR);             if (libraryDirectory == null)                 libraryDirectory = getTmpDir();         } catch (SecurityException e) {             // OK : We don't do AccessController.doPrivileged, but we don't             //      stop the user from creating an MLet just because they             //      can't read the MLET_LIB_DIR or java.io.tmpdir properties             //      either.         }     }       /*      * ------------------------------------------      *  PUBLIC METHODS      * ------------------------------------------      */       /**      * Appends the specified URL to the list of URLs to search for classes and      * resources.      */     public void addURL(URL url) {         if (!Arrays.asList(getURLs()).contains(url))             super.addURL(url);     }      /**      * Appends the specified URL to the list of URLs to search for classes and      * resources.      * @exception ServiceNotFoundException The specified URL is malformed.      */     public void addURL(String url) throws ServiceNotFoundException {         try {             URL ur = new URL(url);             if (!Arrays.asList(getURLs()).contains(ur))                 super.addURL(ur);         } catch (MalformedURLException e) {             if (MLET_LOGGER.isLoggable(Level.FINEST)) {                 MLET_LOGGER.logp(Level.FINEST, MLet.class.getName(),                         "addUrl", "Malformed URL: " + url, e);             }             throw new                 ServiceNotFoundException("The specified URL is malformed");         }     }      /** Returns the search path of URLs for loading classes and resources.      * This includes the original list of URLs specified to the constructor,      * along with any URLs subsequently appended by the addURL() method.      */     public URL[] getURLs() {         return super.getURLs();     }      /**      * Loads a text file containing MLET tags that define the MBeans to      * be added to the MBean server. The location of the text file is specified by      * a URL. The MBeans specified in the MLET file will be instantiated and      * registered in the MBean server.      *      * @param url The URL of the text file to be loaded as URL object.      *      * @return  A set containing one entry per MLET tag in the m-let text file loaded.      * Each entry specifies either the ObjectInstance for the created MBean, or a throwable object      * (that is, an error or an exception) if the MBean could not be created.      *      * @exception ServiceNotFoundException One of the following errors has occurred: The m-let text file does      * not contain an MLET tag, the m-let text file is not found, a mandatory      * attribute of the MLET tag is not specified, the value of url is      * null.      * @exception IllegalStateException MLet MBean is not registered with an MBeanServer.      */     public Set<Object> getMBeansFromURL(URL url)             throws ServiceNotFoundException  {         if (url == null) {             throw new ServiceNotFoundException("The specified URL is null");         }         return getMBeansFromURL(url.toString());     }      /**      * Loads a text file containing MLET tags that define the MBeans to      * be added to the MBean server. The location of the text file is specified by      * a URL. The MBeans specified in the MLET file will be instantiated and      * registered in the MBean server.      *      * @param url The URL of the text file to be loaded as String object.      *      * @return A set containing one entry per MLET tag in the m-let      * text file loaded.  Each entry specifies either the      * ObjectInstance for the created MBean, or a throwable object      * (that is, an error or an exception) if the MBean could not be      * created.      *      * @exception ServiceNotFoundException One of the following      * errors has occurred: The m-let text file does not contain an      * MLET tag, the m-let text file is not found, a mandatory      * attribute of the MLET tag is not specified, the url is      * malformed.      * @exception IllegalStateException MLet MBean is not registered      * with an MBeanServer.      *      */     public Set<Object> getMBeansFromURL(String url)             throws ServiceNotFoundException  {          String mth = "getMBeansFromURL";          if (server == null) {             throw new IllegalStateException("This MLet MBean is not " +                                             "registered with an MBeanServer.");         }         // Parse arguments         if (url == null) {             MLET_LOGGER.logp(Level.FINER, MLet.class.getName(),                     mth, "URL is null");             throw new ServiceNotFoundException("The specified URL is null");         } else {             url = url.replace(File.separatorChar,'/');         }         if (MLET_LOGGER.isLoggable(Level.FINER)) {             MLET_LOGGER.logp(Level.FINER, MLet.class.getName(),                     mth, "<URL = " + url + ">");         }

Lines 1–500 of 1336.