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

Save This Page
Home » commons-modeler-2.0.1-src » org.apache.commons » modeler » [javadoc | source]