Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » tomcat » util » modeler » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.tomcat.util.modeler;
   20   
   21   
   22   import java.io.File;
   23   import java.io.FileInputStream;
   24   import java.io.InputStream;
   25   import java.net.URL;
   26   import java.util.ArrayList;
   27   import java.util.HashMap;
   28   import java.util.Hashtable;
   29   import java.util.Iterator;
   30   import java.util.List;
   31   
   32   import javax.management.DynamicMBean;
   33   import javax.management.MBeanAttributeInfo;
   34   import javax.management.MBeanInfo;
   35   import javax.management.MBeanOperationInfo;
   36   import javax.management.MBeanRegistration;
   37   import javax.management.MBeanServer;
   38   import javax.management.MBeanServerFactory;
   39   import javax.management.MalformedObjectNameException;
   40   import javax.management.ObjectName;
   41   
   42   import org.apache.juli.logging.Log;
   43   import org.apache.juli.logging.LogFactory;
   44   import org.apache.tomcat.util.modeler.modules.ModelerSource;
   45   
   46   /*
   47      Issues:
   48      - exceptions - too many "throws Exception"
   49      - double check the interfaces 
   50      - start removing the use of the experimental methods in tomcat, then remove
   51        the methods ( before 1.1 final )
   52      - is the security enough to prevent Registry beeing used to avoid the permission
   53       checks in the mbean server ?
   54   */ 
   55   
   56   /**
   57    * Registry for modeler MBeans. 
   58    *
   59    * This is the main entry point into modeler. It provides methods to create
   60    * and manipulate model mbeans and simplify their use.
   61    *
   62    * Starting with version 1.1, this is no longer a singleton and the static
   63    * methods are strongly deprecated. In a container environment we can expect
   64    * different applications to use different registries.
   65    * 
   66    * This class is itself an mbean.
   67    * 
   68    * IMPORTANT: public methods not marked with @since x.x are experimental or 
   69    * internal. Should not be used.  
   70    * 
   71    * @author Craig R. McClanahan
   72    * @author Costin Manolache
   73    */
   74   public class Registry implements RegistryMBean, MBeanRegistration  {
   75       /**
   76        * The Log instance to which we will write our log messages.
   77        */
   78       private static Log log = LogFactory.getLog(Registry.class);
   79   
   80       // Support for the factory methods
   81       
   82       /** Will be used to isolate different apps and enhance security.
   83        */
   84       private static HashMap perLoaderRegistries=null;
   85   
   86       /**
   87        * The registry instance created by our factory method the first time
   88        * it is called.
   89        */
   90       private static Registry registry = null;
   91   
   92       // Per registy fields
   93       
   94       /**
   95        * The <code>MBeanServer</code> instance that we will use to register
   96        * management beans.
   97        */
   98       private MBeanServer server = null;
   99   
  100       /**
  101        * The set of ManagedBean instances for the beans this registry
  102        * knows about, keyed by name.
  103        */
  104       private HashMap descriptors = new HashMap();
  105   
  106       /** List of managed byeans, keyed by class name
  107        */
  108       private HashMap descriptorsByClass = new HashMap();
  109   
  110       // map to avoid duplicated searching or loading descriptors 
  111       private HashMap searchedPaths=new HashMap();
  112       
  113       private Object guard;
  114   
  115       // Id - small ints to use array access. No reset on stop()
  116       // Used for notifications
  117       private Hashtable idDomains=new Hashtable();
  118       private Hashtable ids=new Hashtable();
  119   
  120       
  121       // ----------------------------------------------------------- Constructors
  122   
  123       /**
  124        */
  125        public Registry() {
  126           super();
  127       }
  128   
  129       // -------------------- Static methods  --------------------
  130       // Factories
  131       
  132       /**
  133        * Factory method to create (if necessary) and return our
  134        * <code>Registry</code> instance.
  135        *
  136        * Use this method to obtain a Registry - all other static methods
  137        * are deprecated and shouldn't be used.
  138        *
  139        * The current version uses a static - future versions could use
  140        * the thread class loader.
  141        * 
  142        * @param key Support for application isolation. If null, the context class
  143        * loader will be used ( if setUseContextClassLoader is called ) or the 
  144        * default registry is returned. 
  145        * @param guard Prevent access to the registry by untrusted components
  146        *
  147        * @since 1.1
  148        */
  149       public synchronized static Registry getRegistry(Object key, Object guard) {
  150           Registry localRegistry;
  151           if( perLoaderRegistries!=null ) {
  152               if( key==null ) 
  153                   key=Thread.currentThread().getContextClassLoader();
  154               if( key != null ) {
  155                   localRegistry=(Registry)perLoaderRegistries.get(key);
  156                   if( localRegistry == null ) {
  157                       localRegistry=new Registry();
  158   //                    localRegistry.key=key;
  159                       localRegistry.guard=guard;
  160                       perLoaderRegistries.put( key, localRegistry );
  161                       return localRegistry;
  162                   }
  163                   if( localRegistry.guard != null &&
  164                           localRegistry.guard != guard ) {
  165                       return null; // XXX Should I throw a permission ex ? 
  166                   }
  167                   return localRegistry;
  168               }
  169           }
  170   
  171           // static 
  172           if (registry == null) {
  173               registry = new Registry();
  174           }
  175           if( registry.guard != null &&
  176                   registry.guard != guard ) {
  177               return null;
  178           }
  179           return (registry);
  180       }
  181       
  182       /** 
  183        * Allow containers to isolate apps. Can be called only once.
  184        * It  is highly recommended you call this method if using Registry in
  185        * a container environment. The default is false for backward compatibility
  186        * 
  187        * @param enable
  188        * @since 1.1
  189        */
  190       public static void setUseContextClassLoader( boolean enable ) {
  191           if( enable ) {
  192               perLoaderRegistries=new HashMap();
  193           }
  194       }
  195       
  196       // -------------------- Generic methods  --------------------
  197   
  198       /** Lifecycle method - clean up the registry metadata.
  199        *  Called from resetMetadata().
  200        * 
  201        * @since 1.1
  202        */ 
  203       public void stop() {
  204           descriptorsByClass = new HashMap();
  205           descriptors = new HashMap();
  206           searchedPaths=new HashMap();
  207       }
  208       
  209       /** 
  210        * Load an extended mlet file. The source can be an URL, File or
  211        * InputStream. 
  212        * 
  213        * All mbeans will be instantiated, registered and the attributes will be 
  214        * set. The result is a list of ObjectNames.
  215        *
  216        * @param source InputStream or URL of the file
  217        * @param cl ClassLoader to be used to load the mbeans, or null to use the
  218        *        default JMX mechanism ( i.e. all registered loaders )
  219        * @return List of ObjectName for the loaded mbeans
  220        * @throws Exception
  221        * 
  222        * @since 1.1
  223        */ 
  224       public List loadMBeans( Object source, ClassLoader cl )
  225               throws Exception
  226       {
  227           return load("MbeansSource", source, null );
  228       }    
  229   
  230   
  231       /** Load descriptors. The source can be a File or URL or InputStream for the 
  232        * descriptors file. In the case of File and URL, if the extension is ".ser"
  233        * a serialized version will be loaded. 
  234        * 
  235        * This method should be used to explicitely load metadata - but this is not
  236        * required in most cases. The registerComponent() method will find metadata
  237        * in the same pacakge.
  238        * 
  239        * @param source
  240        */ 
  241       public void loadMetadata(Object source ) throws Exception {
  242           loadDescriptors( null, source, null );
  243       }
  244   
  245       /** Register a bean by creating a modeler mbean and adding it to the 
  246        * MBeanServer.
  247        * 
  248        * If metadata is not loaded, we'll look up and read a file named
  249        * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package
  250        * or parent.
  251        *
  252        * If the bean is an instance of DynamicMBean. it's metadata will be converted
  253        * to a model mbean and we'll wrap it - so modeler services will be supported
  254        *
  255        * If the metadata is still not found, introspection will be used to extract
  256        * it automatically. 
  257        * 
  258        * If an mbean is already registered under this name, it'll be first
  259        * unregistered.
  260        * 
  261        * If the component implements MBeanRegistration, the methods will be called.
  262        * If the method has a method "setRegistry" that takes a RegistryMBean as
  263        * parameter, it'll be called with the current registry.
  264        * 
  265        *
  266        * @param bean Object to be registered
  267        * @param oname Name used for registration
  268        * @param type The type of the mbean, as declared in mbeans-descriptors. If
  269        * null, the name of the class will be used. This can be used as a hint or
  270        * by subclasses.
  271        *
  272        * @since 1.1
  273        */ 
  274       public void registerComponent(Object bean, String oname, String type)
  275              throws Exception
  276       {
  277           registerComponent(bean, new ObjectName(oname), type);        
  278       }    
  279   
  280       /** Unregister a component. We'll first check if it is registered,
  281        * and mask all errors. This is mostly a helper.
  282        * 
  283        * @param oname
  284        * 
  285        * @since 1.1
  286        */ 
  287       public void unregisterComponent( String oname ) {
  288           try {
  289               unregisterComponent(new ObjectName(oname));
  290           } catch (MalformedObjectNameException e) {
  291               log.info("Error creating object name " + e );
  292           }
  293       }    
  294       
  295   
  296       /** Invoke a operation on a list of mbeans. Can be used to implement
  297        * lifecycle operations.
  298        *
  299        * @param mbeans list of ObjectName on which we'll invoke the operations
  300        * @param operation  Name of the operation ( init, start, stop, etc)
  301        * @param failFirst  If false, exceptions will be ignored
  302        * @throws Exception
  303        * @since 1.1
  304        */
  305       public void invoke( List mbeans, String operation, boolean failFirst )
  306               throws Exception
  307       {
  308           if( mbeans==null ) {
  309               return;
  310           }
  311           Iterator itr=mbeans.iterator();
  312           while(itr.hasNext()) {
  313               Object current=itr.next();
  314               ObjectName oN=null;
  315               try {
  316                   if( current instanceof ObjectName) {
  317                       oN=(ObjectName)current;
  318                   }
  319                   if( current instanceof String ) {
  320                       oN=new ObjectName( (String)current );
  321                   }
  322                   if( oN==null ) {
  323                       continue;
  324                   }
  325                   if( getMethodInfo(oN, operation) == null) {
  326                       continue;
  327                   }
  328                   getMBeanServer().invoke(oN, operation,
  329                           new Object[] {}, new String[] {});
  330   
  331               } catch( Exception t ) {
  332                   if( failFirst ) throw t;
  333                   log.info("Error initializing " + current + " " + t.toString());
  334               }
  335           }
  336       }
  337   
  338       // -------------------- ID registry --------------------
  339   
  340       /** Return an int ID for faster access. Will be used for notifications
  341        * and for other operations we want to optimize. 
  342        *
  343        * @param domain Namespace 
  344        * @param name  Type of the notification
  345        * @return  An unique id for the domain:name combination
  346        * @since 1.1
  347        */
  348       public synchronized int getId( String domain, String name) {
  349           if( domain==null) {
  350               domain="";
  351           }
  352           Hashtable domainTable=(Hashtable)idDomains.get( domain );
  353           if( domainTable == null ) {
  354               domainTable=new Hashtable();
  355               idDomains.put( domain, domainTable); 
  356           }
  357           if( name==null ) {
  358               name="";
  359           }
  360           Integer i=(Integer)domainTable.get(name);
  361           
  362           if( i!= null ) {
  363               return i.intValue();
  364           }
  365   
  366           int id[]=(int [])ids.get( domain );
  367           if( id == null ) {
  368               id=new int[1];
  369               ids.put( domain, id); 
  370           }
  371           int code=id[0]++;
  372           domainTable.put( name, new Integer( code ));
  373           return code;
  374       }
  375       
  376       // -------------------- Metadata   --------------------
  377       // methods from 1.0
  378   
  379       /**
  380        * Add a new bean metadata to the set of beans known to this registry.
  381        * This is used by internal components.
  382        *
  383        * @param bean The managed bean to be added
  384        * @since 1.0
  385        */
  386       public void addManagedBean(ManagedBean bean) {
  387           // XXX Use group + name
  388           descriptors.put(bean.getName(), bean);
  389           if( bean.getType() != null ) {
  390               descriptorsByClass.put( bean.getType(), bean );
  391           }
  392       }
  393   
  394   
  395       /**
  396        * Find and return the managed bean definition for the specified
  397        * bean name, if any; otherwise return <code>null</code>.
  398        *
  399        * @param name Name of the managed bean to be returned. Since 1.1, both
  400        *   short names or the full name of the class can be used.
  401        * @since 1.0
  402        */
  403       public ManagedBean findManagedBean(String name) {
  404           // XXX Group ?? Use Group + Type
  405           ManagedBean mb=((ManagedBean) descriptors.get(name));
  406           if( mb==null )
  407               mb=(ManagedBean)descriptorsByClass.get(name);
  408           return mb;
  409       }
  410       
  411       /**
  412        * Return the set of bean names for all managed beans known to
  413        * this registry.
  414        *
  415        * @since 1.0
  416        */
  417       public String[] findManagedBeans() {
  418           return ((String[]) descriptors.keySet().toArray(new String[0]));
  419       }
  420   
  421   
  422       /**
  423        * Return the set of bean names for all managed beans known to
  424        * this registry that belong to the specified group.
  425        *
  426        * @param group Name of the group of interest, or <code>null</code>
  427        *  to select beans that do <em>not</em> belong to a group
  428        * @since 1.0
  429        */
  430       public String[] findManagedBeans(String group) {
  431   
  432           ArrayList results = new ArrayList();
  433           Iterator items = descriptors.values().iterator();
  434           while (items.hasNext()) {
  435               ManagedBean item = (ManagedBean) items.next();
  436               if ((group == null) && (item.getGroup() == null)) {
  437                   results.add(item.getName());
  438               } else if (group.equals(item.getGroup())) {
  439                   results.add(item.getName());
  440               }
  441           }
  442           String values[] = new String[results.size()];
  443           return ((String[]) results.toArray(values));
  444   
  445       }
  446   
  447   
  448       /**
  449        * Remove an existing bean from the set of beans known to this registry.
  450        *
  451        * @param bean The managed bean to be removed
  452        * @since 1.0
  453        */
  454       public void removeManagedBean(ManagedBean bean) {
  455          // TODO: change this to use group/name
  456           descriptors.remove(bean.getName());
  457           descriptorsByClass.remove( bean.getType());
  458       }
  459   
  460       // -------------------- Deprecated 1.0 methods  --------------------
  461       
  462       /**
  463        * Factory method to create (if necessary) and return our
  464        * <code>MBeanServer</code> instance.
  465        *
  466        * @since 1.0
  467        * @deprecated Use the instance method
  468        */
  469       public static MBeanServer getServer() {
  470           return Registry.getRegistry().getMBeanServer();
  471       }
  472   
  473       /**
  474        * Set the <code>MBeanServer</code> to be utilized for our
  475        * registered management beans.
  476        *
  477        * @param mbeanServer The new <code>MBeanServer</code> instance
  478        * @since 1.0
  479        * @deprecated Use the instance method
  480        */
  481       public static void setServer(MBeanServer mbeanServer) {
  482           Registry.getRegistry().setMBeanServer(mbeanServer);
  483       }
  484   
  485       /**
  486        * Load the registry from the XML input found in the specified input
  487        * stream.
  488        *
  489        * @param stream InputStream containing the registry configuration
  490        *  information
  491        *
  492        * @exception Exception if any parsing or processing error occurs
  493        * @deprecated use normal class method instead
  494        * @since 1.0
  495        */
  496       public static void loadRegistry(InputStream stream) throws Exception {
  497           Registry registry = getRegistry();
  498           registry.loadMetadata(stream);
  499       }
  500   
  501       /** Get a "singelton" registry, or one per thread if setUseContextLoader 
  502        * was called 
  503        * 
  504        * @deprecated Not enough info - use the method that takes CL and domain
  505        * @since 1.0 
  506        */ 
  507       public synchronized static Registry getRegistry() {
  508           return getRegistry(null, null);
  509       }    
  510   
  511       // -------------------- Helpers  --------------------
  512   
  513       /** Get the type of an attribute of the object, from the metadata.
  514        *
  515        * @param oname
  516        * @param attName
  517        * @return null if metadata about the attribute is not found
  518        * @since 1.1
  519        */
  520       public String getType( ObjectName oname, String attName )
  521       {
  522           String type=null;
  523           MBeanInfo info=null;
  524           try {
  525               info=server.getMBeanInfo(oname);
  526           } catch (Exception e) {
  527               log.info( "Can't find metadata for object" + oname );
  528               return null;
  529           }
  530   
  531           MBeanAttributeInfo attInfo[]=info.getAttributes();
  532           for( int i=0; i<attInfo.length; i++ ) {
  533               if( attName.equals(attInfo[i].getName())) {
  534                   type=attInfo[i].getType();
  535                   return type;
  536               }
  537           }
  538           return null;
  539       }
  540   
  541       /** Find the operation info for a method
  542        * 
  543        * @param oname
  544        * @param opName
  545        * @return the operation info for the specified operation
  546        */ 
  547       public MBeanOperationInfo getMethodInfo( ObjectName oname, String opName )
  548       {
  549           String type=null;
  550           MBeanInfo info=null;
  551           try {
  552               info=server.getMBeanInfo(oname);
  553           } catch (Exception e) {
  554               log.info( "Can't find metadata " + oname );
  555               return null;
  556           }
  557           MBeanOperationInfo attInfo[]=info.getOperations();
  558           for( int i=0; i<attInfo.length; i++ ) {
  559               if( opName.equals(attInfo[i].getName())) {
  560                   return attInfo[i];
  561               }
  562           }
  563           return null;
  564       }
  565   
  566       /** Unregister a component. This is just a helper that
  567        * avoids exceptions by checking if the mbean is already registered
  568        *
  569        * @param oname
  570        */
  571       public void unregisterComponent( ObjectName oname ) {
  572           try {
  573               if( getMBeanServer().isRegistered(oname)) {
  574                   getMBeanServer().unregisterMBean(oname);
  575               }
  576           } catch( Throwable t ) {
  577               log.error( "Error unregistering mbean ", t);
  578           }
  579       }
  580   
  581       /**
  582        * Factory method to create (if necessary) and return our
  583        * <code>MBeanServer</code> instance.
  584        *
  585        */
  586       public synchronized MBeanServer getMBeanServer() {
  587           long t1=System.currentTimeMillis();
  588   
  589           if (server == null) {
  590               if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {
  591                   server=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);
  592                   if( log.isDebugEnabled() ) {
  593                       log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1 ));
  594                   }
  595               } else {
  596                   server=MBeanServerFactory.createMBeanServer();
  597                   if( log.isDebugEnabled() ) {
  598                       log.debug("Creating MBeanServer"+ (System.currentTimeMillis() - t1 ));
  599                   }
  600               }
  601           }
  602           return (server);
  603       }
  604   
  605       /** Find or load metadata. 
  606        */ 
  607       public ManagedBean findManagedBean(Object bean, Class beanClass, String type)
  608           throws Exception
  609       {
  610           if( bean!=null && beanClass==null ) {
  611               beanClass=bean.getClass();
  612           }
  613           
  614           if( type==null ) {
  615               type=beanClass.getName();
  616           }
  617           
  618           // first look for existing descriptor
  619           ManagedBean managed = findManagedBean(type);
  620   
  621           // Search for a descriptor in the same package
  622           if( managed==null ) {
  623               // check package and parent packages
  624               if( log.isDebugEnabled() ) {
  625                   log.debug( "Looking for descriptor ");
  626               }
  627               findDescriptor( beanClass, type );
  628   
  629               managed=findManagedBean(type);
  630           }
  631           
  632           if( bean instanceof DynamicMBean ) {
  633               if( log.isDebugEnabled() ) {
  634                   log.debug( "Dynamic mbean support ");
  635               }
  636               // Dynamic mbean
  637               loadDescriptors("MbeansDescriptorsDynamicMBeanSource",
  638                       bean, type);
  639   
  640               managed=findManagedBean(type);
  641           }
  642   
  643           // Still not found - use introspection
  644           if( managed==null ) {
  645               if( log.isDebugEnabled() ) {
  646                   log.debug( "Introspecting ");
  647               }
  648   
  649               // introspection
  650               loadDescriptors("MbeansDescriptorsIntrospectionSource",
  651                       beanClass, type);
  652   
  653               managed=findManagedBean(type);
  654               if( managed==null ) {
  655                   log.warn( "No metadata found for " + type );
  656                   return null;
  657               }
  658               managed.setName( type );
  659               addManagedBean(managed);
  660           }
  661           return managed;
  662       }
  663       
  664   
  665       /** EXPERIMENTAL Convert a string to object, based on type. Used by several
  666        * components. We could provide some pluggability. It is here to keep
  667        * things consistent and avoid duplication in other tasks 
  668        * 
  669        * @param type Fully qualified class name of the resulting value
  670        * @param value String value to be converted
  671        * @return Converted value
  672        */ 
  673       public Object convertValue(String type, String value)
  674       {
  675           Object objValue=value;
  676           
  677           if( type==null || "java.lang.String".equals( type )) {
  678               // string is default
  679               objValue=value;
  680           } else if( "javax.management.ObjectName".equals( type ) ||
  681                   "ObjectName".equals( type )) {
  682               try {
  683                   objValue=new ObjectName( value );
  684               } catch (MalformedObjectNameException e) {
  685                   return null;
  686               }
  687           } else if( "java.lang.Integer".equals( type ) ||
  688                   "int".equals( type )) {
  689               objValue=new Integer( value );
  690           } else if( "java.lang.Long".equals( type ) ||
  691                   "long".equals( type )) {
  692               objValue=new Long( value );
  693           } else if( "java.lang.Boolean".equals( type ) ||
  694                   "boolean".equals( type )) {
  695               objValue=new Boolean( value );
  696           }
  697           return objValue;
  698       }
  699       
  700       /** Experimental.
  701        *
  702        * @param sourceType
  703        * @param source
  704        * @param param
  705        * @return List of descriptors
  706        * @throws Exception
  707        * @deprecated bad interface, mixing of metadata and mbeans
  708        */
  709       public List load( String sourceType, Object source, String param)
  710           throws Exception
  711       {
  712           if( log.isTraceEnabled()) {
  713               log.trace("load " + source );
  714           }
  715           String location=null;
  716           String type=null;
  717           Object inputsource=null;
  718   
  719           if( source instanceof DynamicMBean ) {
  720               sourceType="MbeansDescriptorsDynamicMBeanSource";
  721               inputsource=source;
  722           } else if( source instanceof URL ) {
  723               URL url=(URL)source;
  724               location=url.toString();
  725               type=param;
  726               inputsource=url.openStream();
  727               if( sourceType == null ) {
  728                   sourceType = sourceTypeFromExt(location);
  729               }
  730           } else if( source instanceof File ) {
  731               location=((File)source).getAbsolutePath();
  732               inputsource=new FileInputStream((File)source);            
  733               type=param;
  734               if( sourceType == null ) {
  735                   sourceType = sourceTypeFromExt(location);
  736               }
  737           } else if( source instanceof InputStream ) {
  738               type=param;
  739               inputsource=source;
  740           } else if( source instanceof Class ) {
  741               location=((Class)source).getName();
  742               type=param;
  743               inputsource=source;
  744               if( sourceType== null ) {
  745                   sourceType="MbeansDescriptorsIntrospectionSource";
  746               }
  747           }
  748           
  749           if( sourceType==null ) {
  750               sourceType="MbeansDescriptorsDigesterSource";
  751           }
  752           ModelerSource ds=getModelerSource(sourceType);
  753           List mbeans=ds.loadDescriptors(this, location, type, inputsource);
  754   
  755           return mbeans;
  756       }
  757   
  758       private String sourceTypeFromExt( String s ) {
  759           if( s.endsWith( ".ser")) {
  760               return "MbeansDescriptorsSerSource";
  761           }
  762           else if( s.endsWith(".xml")) {
  763               return "MbeansDescriptorsDigesterSource";
  764           }
  765           return null;
  766       }
  767   
  768       /** Register a component 
  769        * XXX make it private 
  770        * 
  771        * @param bean
  772        * @param oname
  773        * @param type
  774        * @throws Exception
  775        */ 
  776       public void registerComponent(Object bean, ObjectName oname, String type)
  777              throws Exception
  778       {
  779           if( log.isDebugEnabled() ) {
  780               log.debug( "Managed= "+ oname);
  781           }
  782   
  783           if( bean ==null ) {
  784               log.error("Null component " + oname );
  785               return;
  786           }
  787   
  788           try {
  789               if( type==null ) {
  790                   type=bean.getClass().getName();
  791               }
  792   
  793               ManagedBean managed = findManagedBean(bean.getClass(), type);
  794   
  795               // The real mbean is created and registered
  796               DynamicMBean mbean = managed.createMBean(bean);
  797   
  798               if(  getMBeanServer().isRegistered( oname )) {
  799                   if( log.isDebugEnabled()) {
  800                       log.debug("Unregistering existing component " + oname );
  801                   }
  802                   getMBeanServer().unregisterMBean( oname );
  803               }
  804   
  805               getMBeanServer().registerMBean( mbean, oname);
  806           } catch( Exception ex) {
  807               log.error("Error registering " + oname, ex );
  808               throw ex;
  809           }
  810       }
  811   
  812       /** Lookup the component descriptor in the package and
  813        * in the parent packages.
  814        *
  815        * @param packageName
  816        */
  817       public void loadDescriptors( String packageName, ClassLoader classLoader  ) {
  818           String res=packageName.replace( '.', '/');
  819   
  820           if( log.isTraceEnabled() ) {
  821               log.trace("Finding descriptor " + res );
  822           }
  823   
  824           if( searchedPaths.get( packageName ) != null ) {
  825               return;
  826           }
  827           String descriptors=res + "/mbeans-descriptors.ser";
  828   
  829           URL dURL=classLoader.getResource( descriptors );
  830   
  831           if( dURL == null ) {
  832               descriptors=res + "/mbeans-descriptors.xml";
  833               dURL=classLoader.getResource( descriptors );
  834           }
  835           if( dURL == null ) {
  836               return;
  837           }
  838   
  839           log.debug( "Found " + dURL);
  840           searchedPaths.put( packageName,  dURL );
  841           try {
  842               if( descriptors.endsWith(".xml" ))
  843                   loadDescriptors("MbeansDescriptorsDigesterSource", dURL, null);
  844               else
  845                   loadDescriptors("MbeansDescriptorsSerSource", dURL, null);
  846               return;
  847           } catch(Exception ex ) {
  848               log.error("Error loading " + dURL);
  849           }
  850   
  851           return;
  852       }
  853   
  854       /** Experimental. Will become private, some code may still use it
  855        *
  856        * @param sourceType
  857        * @param source
  858        * @param param
  859        * @throws Exception
  860        * @deprecated
  861        */
  862       public void loadDescriptors( String sourceType, Object source, String param)
  863           throws Exception
  864       {
  865           List mbeans=load( sourceType, source, param );
  866           if( mbeans == null) return;
  867   
  868           Iterator itr=mbeans.iterator();
  869           while( itr.hasNext() ) {
  870               Object mb=itr.next();
  871               if( mb instanceof ManagedBean) {
  872                   addManagedBean((ManagedBean)mb);
  873               }
  874           }
  875       }
  876   
  877       /** Lookup the component descriptor in the package and
  878        * in the parent packages.
  879        *
  880        * @param beanClass
  881        * @param type
  882        */
  883       private void findDescriptor( Class beanClass, String type ) {
  884           if( type==null ) {
  885               type=beanClass.getName();
  886           }
  887           ClassLoader classLoader=null;
  888           if( beanClass!=null ) {
  889               classLoader=beanClass.getClassLoader();
  890           }
  891           if( classLoader==null ) {
  892               classLoader=Thread.currentThread().getContextClassLoader();
  893           }
  894           if( classLoader==null ) {
  895               classLoader=this.getClass().getClassLoader();
  896           }
  897           
  898           String className=type;
  899           String pkg=className;
  900           while( pkg.indexOf( ".") > 0 ) {
  901               int lastComp=pkg.lastIndexOf( ".");
  902               if( lastComp <= 0 ) return;
  903               pkg=pkg.substring(0, lastComp);
  904               if( searchedPaths.get( pkg ) != null ) {
  905                   return;
  906               }
  907               loadDescriptors(pkg, classLoader);
  908           }
  909           return;
  910       }
  911   
  912       private ModelerSource getModelerSource( String type )
  913               throws Exception
  914       {
  915           if( type==null ) type="MbeansDescriptorsDigesterSource";
  916           if( type.indexOf( ".") < 0 ) {
  917               type="org.apache.tomcat.util.modeler.modules." + type;
  918           }
  919   
  920           Class c=Class.forName( type );
  921           ModelerSource ds=(ModelerSource)c.newInstance();
  922           return ds;
  923       }
  924   
  925   
  926       // -------------------- Registration  --------------------
  927       
  928       public ObjectName preRegister(MBeanServer server,
  929                                     ObjectName name) throws Exception 
  930       {
  931           this.server=server;
  932           return name;
  933       }
  934   
  935       public void postRegister(Boolean registrationDone) {
  936       }
  937   
  938       public void preDeregister() throws Exception {
  939       }
  940   
  941       public void postDeregister() {
  942       }
  943   
  944       
  945       
  946       
  947       // -------------------- DEPRECATED METHODS  --------------------
  948       // May still be used in tomcat 
  949       // Never part of an official release
  950       
  951       /** Called by a registry or by the container to unload a loader
  952        * @param loader
  953        */
  954       public void unregisterRegistry(ClassLoader loader ) {
  955           // XXX Cleanup ?
  956           perLoaderRegistries.remove(loader);
  957       }
  958   
  959       public ManagedBean findManagedBean(Class beanClass, String type)
  960           throws Exception
  961       {
  962           return findManagedBean(null, beanClass, type);        
  963       }
  964       
  965       /**
  966        * Set the <code>MBeanServer</code> to be utilized for our
  967        * registered management beans.
  968        *
  969        * @param server The new <code>MBeanServer</code> instance
  970        */
  971       public void setMBeanServer( MBeanServer server ) {
  972           this.server=server;
  973       }
  974   
  975       public void resetMetadata() {
  976           stop();
  977       }
  978       /**
  979        * Load the registry from the XML input found in the specified input
  980        * stream.
  981        *
  982        * @param source Source to be used to load. Can be an InputStream or URL.
  983        *
  984        * @exception Exception if any parsing or processing error occurs
  985        */
  986       public void loadDescriptors( Object source )
  987               throws Exception
  988       {
  989           loadDescriptors("MbeansDescriptorsDigesterSource", source, null );
  990       }
  991   
  992       /** @deprecated - may still be used in code using pre-1.1 builds
  993        */
  994       public void registerComponent(Object bean, String domain, String type,
  995                                     String name)
  996               throws Exception
  997       {
  998           StringBuffer sb=new StringBuffer();
  999           sb.append( domain ).append(":");
 1000           sb.append( name );
 1001           String nameStr=sb.toString();
 1002           ObjectName oname=new ObjectName( nameStr );
 1003           registerComponent(bean, oname, type );
 1004       }
 1005   
 1006       
 1007   
 1008       // should be removed
 1009       public void unregisterComponent( String domain, String name ) {
 1010           try {
 1011               ObjectName oname=new ObjectName( domain + ":" + name );
 1012   
 1013               // XXX remove from our tables.
 1014               getMBeanServer().unregisterMBean( oname );
 1015           } catch( Throwable t ) {
 1016               log.error( "Error unregistering mbean ", t );
 1017           }
 1018       }
 1019       
 1020   
 1021       /**
 1022        * Load the registry from a cached .ser file. This is typically 2-3 times
 1023        * faster than parsing the XML.
 1024        *
 1025        * @param source Source to be used to load. Can be an InputStream or URL.
 1026        *
 1027        * @exception Exception if any parsing or processing error occurs
 1028        * @deprecated Loaded automatically or using a File or Url ending in .ser
 1029        */
 1030       public void loadCachedDescriptors( Object source )
 1031               throws Exception
 1032       {
 1033           loadDescriptors("MbeansDescriptorsSerSource", source, null );
 1034       }
 1035   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » tomcat » util » modeler » [javadoc | source]