Home » apache-tomcat-6.0.26-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.lang.reflect.InvocationTargetException;
   23   import java.lang.reflect.Method;
   24   import java.util.Iterator;
   25   
   26   import javax.management.Attribute;
   27   import javax.management.AttributeChangeNotification;
   28   import javax.management.AttributeList;
   29   import javax.management.AttributeNotFoundException;
   30   import javax.management.DynamicMBean;
   31   import javax.management.InstanceNotFoundException;
   32   import javax.management.InvalidAttributeValueException;
   33   import javax.management.ListenerNotFoundException;
   34   import javax.management.MBeanException;
   35   import javax.management.MBeanInfo;
   36   import javax.management.MBeanNotificationInfo;
   37   import javax.management.MBeanRegistration;
   38   import javax.management.MBeanServer;
   39   import javax.management.Notification;
   40   import javax.management.NotificationFilter;
   41   import javax.management.NotificationListener;
   42   import javax.management.ObjectName;
   43   import javax.management.ReflectionException;
   44   import javax.management.RuntimeErrorException;
   45   import javax.management.RuntimeOperationsException;
   46   import javax.management.modelmbean.InvalidTargetObjectTypeException;
   47   import javax.management.modelmbean.ModelMBeanNotificationBroadcaster;
   48   
   49   import org.apache.juli.logging.Log;
   50   import org.apache.juli.logging.LogFactory;
   51   
   52   /*
   53    * Changes from commons.modeler:
   54    * 
   55    *  - use DynamicMBean
   56    *  - remove methods not used in tomcat and redundant/not very generic
   57    *  - must be created from the ManagedBean - I don't think there were any direct
   58    *    uses, but now it is required.
   59    *  - some of the gratuituous flexibility removed - instead this is more predictive and
   60    *    strict with the use cases.
   61    *  - all Method and metadata is stored in ManagedBean. BaseModelBMean and ManagedBean act
   62    *    like Object and Class. 
   63    *  - setModelMBean is no longer called on resources ( not used in tomcat )
   64    *  - no caching of Methods for now - operations and setters are not called repeatedly in most 
   65    *  management use cases. Getters should't be called very frequently either - and even if they
   66    *  are, the overhead of getting the method should be small compared with other JMX costs ( RMI, etc ).
   67    *  We can add getter cache if needed.
   68    *  - removed unused constructor, fields
   69    *  
   70    *  TODO:
   71    *   - clean up catalina.mbeans, stop using weird inheritance
   72    */
   73   
   74   /**
   75    * <p>Basic implementation of the <code>DynamicMBean</code> interface, which
   76    * supports the minimal requirements of the interface contract.</p>
   77    *
   78    * <p>This can be used directly to wrap an existing java bean, or inside
   79    * an mlet or anywhere an MBean would be used. 
   80    *
   81    * Limitations:
   82    * <ul>
   83    * <li>Only managed resources of type <code>objectReference</code> are
   84    *     supportd.</li>
   85    * <li>Caching of attribute values and operation results is not supported.
   86    *     All calls to <code>invoke()</code> are immediately executed.</li>
   87    * <li>Persistence of MBean attributes and operations is not supported.</li>
   88    * <li>All classes referenced as attribute types, operation parameters, or
   89    *     operation return values must be one of the following:
   90    *     <ul>
   91    *     <li>One of the Java primitive types (boolean, byte, char, double,
   92    *         float, integer, long, short).  Corresponding value will be wrapped
   93    *         in the appropriate wrapper class automatically.</li>
   94    *     <li>Operations that return no value should declare a return type of
   95    *         <code>void</code>.</li>
   96    *     </ul>
   97    * <li>Attribute caching is not supported</li>
   98    * </ul>
   99    *
  100    * @author Craig R. McClanahan
  101    * @author Costin Manolache
  102    */
  103   public class BaseModelMBean implements DynamicMBean, MBeanRegistration, ModelMBeanNotificationBroadcaster {
  104       private static Log log = LogFactory.getLog(BaseModelMBean.class);
  105   
  106       // ----------------------------------------------------------- Constructors
  107   
  108       /**
  109        * Construct a <code>ModelMBean</code> with default
  110        * <code>ModelMBeanInfo</code> information.
  111        *
  112        * @exception MBeanException if the initializer of an object
  113        *  throws an exception
  114        * @exception RuntimeOperationsException if an IllegalArgumentException
  115        *  occurs
  116        */
  117       protected BaseModelMBean() throws MBeanException, RuntimeOperationsException {
  118           super();
  119       }
  120   
  121       // ----------------------------------------------------- Instance Variables
  122   
  123       protected ObjectName oname=null;
  124   
  125       /**
  126        * Notification broadcaster for attribute changes.
  127        */
  128       protected BaseNotificationBroadcaster attributeBroadcaster = null;
  129   
  130       /**
  131        * Notification broadcaster for general notifications.
  132        */
  133       protected BaseNotificationBroadcaster generalBroadcaster = null;
  134       
  135       /** Metadata for the mbean instance.
  136        */
  137       protected ManagedBean managedBean = null;
  138   
  139       /**
  140        * The managed resource this MBean is associated with (if any).
  141        */
  142       protected Object resource = null;
  143   
  144       // --------------------------------------------------- DynamicMBean Methods
  145       // TODO: move to ManagedBean
  146       static final Object[] NO_ARGS_PARAM=new Object[0];
  147       static final Class[] NO_ARGS_PARAM_SIG=new Class[0];
  148       
  149       protected String resourceType = null;
  150   
  151       // key: operation val: invoke method
  152       //private Hashtable invokeAttMap=new Hashtable();
  153   
  154       /**
  155        * Obtain and return the value of a specific attribute of this MBean.
  156        *
  157        * @param name Name of the requested attribute
  158        *
  159        * @exception AttributeNotFoundException if this attribute is not
  160        *  supported by this MBean
  161        * @exception MBeanException if the initializer of an object
  162        *  throws an exception
  163        * @exception ReflectionException if a Java reflection exception
  164        *  occurs when invoking the getter
  165        */
  166       public Object getAttribute(String name)
  167           throws AttributeNotFoundException, MBeanException,
  168               ReflectionException {
  169           // Validate the input parameters
  170           if (name == null)
  171               throw new RuntimeOperationsException
  172                   (new IllegalArgumentException("Attribute name is null"),
  173                    "Attribute name is null");
  174   
  175           if( (resource instanceof DynamicMBean) && 
  176                ! ( resource instanceof BaseModelMBean )) {
  177               return ((DynamicMBean)resource).getAttribute(name);
  178           }
  179           
  180           Method m=managedBean.getGetter(name, this, resource);
  181           Object result = null;
  182           try {
  183               Class declaring=m.getDeclaringClass();
  184               // workaround for catalina weird mbeans - the declaring class is BaseModelMBean.
  185               // but this is the catalina class.
  186               if( declaring.isAssignableFrom(this.getClass()) ) {
  187                   result = m.invoke(this, NO_ARGS_PARAM );
  188               } else {
  189                   result = m.invoke(resource, NO_ARGS_PARAM );
  190               }
  191           } catch (InvocationTargetException e) {
  192               Throwable t = e.getTargetException();
  193               if (t == null)
  194                   t = e;
  195               if (t instanceof RuntimeException)
  196                   throw new RuntimeOperationsException
  197                       ((RuntimeException) t, "Exception invoking method " + name);
  198               else if (t instanceof Error)
  199                   throw new RuntimeErrorException
  200                       ((Error) t, "Error invoking method " + name);
  201               else
  202                   throw new MBeanException
  203                       (e, "Exception invoking method " + name);
  204           } catch (Exception e) {
  205               throw new MBeanException
  206                   (e, "Exception invoking method " + name);
  207           }
  208   
  209           // Return the results of this method invocation
  210           // FIXME - should we validate the return type?
  211           return (result);
  212       }
  213   
  214   
  215       /**
  216        * Obtain and return the values of several attributes of this MBean.
  217        *
  218        * @param names Names of the requested attributes
  219        */
  220       public AttributeList getAttributes(String names[]) {
  221   
  222           // Validate the input parameters
  223           if (names == null)
  224               throw new RuntimeOperationsException
  225                   (new IllegalArgumentException("Attribute names list is null"),
  226                    "Attribute names list is null");
  227   
  228           // Prepare our response, eating all exceptions
  229           AttributeList response = new AttributeList();
  230           for (int i = 0; i < names.length; i++) {
  231               try {
  232                   response.add(new Attribute(names[i],getAttribute(names[i])));
  233               } catch (Exception e) {
  234                   ; // Not having a particular attribute in the response
  235                   ; // is the indication of a getter problem
  236               }
  237           }
  238           return (response);
  239   
  240       }
  241   
  242       public void setManagedBean(ManagedBean managedBean) {
  243           this.managedBean = managedBean;
  244       }
  245   
  246       /**
  247        * Return the <code>MBeanInfo</code> object for this MBean.
  248        */
  249       public MBeanInfo getMBeanInfo() {
  250           return managedBean.getMBeanInfo();
  251       }
  252   
  253   
  254       /**
  255        * Invoke a particular method on this MBean, and return any returned
  256        * value.
  257        *
  258        * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation will
  259        * attempt to invoke this method on the MBean itself, or (if not
  260        * available) on the managed resource object associated with this
  261        * MBean.</p>
  262        *
  263        * @param name Name of the operation to be invoked
  264        * @param params Array containing the method parameters of this operation
  265        * @param signature Array containing the class names representing
  266        *  the signature of this operation
  267        *
  268        * @exception MBeanException if the initializer of an object
  269        *  throws an exception
  270        * @exception ReflectioNException if a Java reflection exception
  271        *  occurs when invoking a method
  272        */
  273       public Object invoke(String name, Object params[], String signature[])
  274           throws MBeanException, ReflectionException 
  275       {
  276           if( (resource instanceof DynamicMBean) && 
  277                ! ( resource instanceof BaseModelMBean )) {
  278               return ((DynamicMBean)resource).invoke(name, params, signature);
  279           }
  280       
  281           // Validate the input parameters
  282           if (name == null)
  283               throw new RuntimeOperationsException
  284                   (new IllegalArgumentException("Method name is null"),
  285                    "Method name is null");
  286   
  287           if( log.isDebugEnabled()) log.debug("Invoke " + name);
  288   	MethodKey mkey = new MethodKey(name, signature);
  289           Method method= managedBean.getInvoke(name, params, signature, this, resource);
  290           
  291           // Invoke the selected method on the appropriate object
  292           Object result = null;
  293           try {
  294               if( method.getDeclaringClass().isAssignableFrom( this.getClass()) ) {
  295                   result = method.invoke(this, params );
  296               } else {
  297                   result = method.invoke(resource, params);
  298               }
  299           } catch (InvocationTargetException e) {
  300               Throwable t = e.getTargetException();
  301               log.error("Exception invoking method " + name , t );
  302               if (t == null)
  303                   t = e;
  304               if (t instanceof RuntimeException)
  305                   throw new RuntimeOperationsException
  306                       ((RuntimeException) t, "Exception invoking method " + name);
  307               else if (t instanceof Error)
  308                   throw new RuntimeErrorException
  309                       ((Error) t, "Error invoking method " + name);
  310               else
  311                   throw new MBeanException
  312                       ((Exception)t, "Exception invoking method " + name);
  313           } catch (Exception e) {
  314               log.error("Exception invoking method " + name , e );
  315               throw new MBeanException
  316                   (e, "Exception invoking method " + name);
  317           }
  318   
  319           // Return the results of this method invocation
  320           // FIXME - should we validate the return type?
  321           return (result);
  322   
  323       }
  324   
  325       static Class getAttributeClass(String signature)
  326           throws ReflectionException
  327       {
  328           if (signature.equals(Boolean.TYPE.getName()))
  329               return Boolean.TYPE;
  330           else if (signature.equals(Byte.TYPE.getName()))
  331               return Byte.TYPE;
  332           else if (signature.equals(Character.TYPE.getName()))
  333               return Character.TYPE;
  334           else if (signature.equals(Double.TYPE.getName()))
  335               return Double.TYPE;
  336           else if (signature.equals(Float.TYPE.getName()))
  337               return Float.TYPE;
  338           else if (signature.equals(Integer.TYPE.getName()))
  339               return Integer.TYPE;
  340           else if (signature.equals(Long.TYPE.getName()))
  341               return Long.TYPE;
  342           else if (signature.equals(Short.TYPE.getName()))
  343               return Short.TYPE;
  344           else {
  345               try {
  346                   ClassLoader cl=Thread.currentThread().getContextClassLoader();
  347                   if( cl!=null )
  348                       return cl.loadClass(signature); 
  349               } catch( ClassNotFoundException e ) {
  350               }
  351               try {
  352                   return Class.forName(signature);
  353               } catch (ClassNotFoundException e) {
  354                   throw new ReflectionException
  355                       (e, "Cannot find Class for " + signature);
  356               }
  357           }
  358       }
  359   
  360       /**
  361        * Set the value of a specific attribute of this MBean.
  362        *
  363        * @param attribute The identification of the attribute to be set
  364        *  and the new value
  365        *
  366        * @exception AttributeNotFoundException if this attribute is not
  367        *  supported by this MBean
  368        * @exception MBeanException if the initializer of an object
  369        *  throws an exception
  370        * @exception ReflectionException if a Java reflection exception
  371        *  occurs when invoking the getter
  372        */
  373       public void setAttribute(Attribute attribute)
  374           throws AttributeNotFoundException, MBeanException,
  375           ReflectionException
  376       {
  377           if( log.isDebugEnabled() )
  378               log.debug("Setting attribute " + this + " " + attribute );
  379   
  380           if( (resource instanceof DynamicMBean) && 
  381                ! ( resource instanceof BaseModelMBean )) {
  382               try {
  383                   ((DynamicMBean)resource).setAttribute(attribute);
  384               } catch (InvalidAttributeValueException e) {
  385                   throw new MBeanException(e);                
  386               }
  387               return;
  388           }
  389           
  390           // Validate the input parameters
  391           if (attribute == null)
  392               throw new RuntimeOperationsException
  393                   (new IllegalArgumentException("Attribute is null"),
  394                    "Attribute is null");
  395   
  396           String name = attribute.getName();
  397           Object value = attribute.getValue();
  398   
  399           if (name == null)
  400               throw new RuntimeOperationsException
  401                   (new IllegalArgumentException("Attribute name is null"),
  402                    "Attribute name is null");
  403   
  404           Object oldValue=null;
  405           //if( getAttMap.get(name) != null )
  406           //    oldValue=getAttribute( name );
  407   
  408           Method m=managedBean.getSetter(name,this,resource);
  409   
  410           try {
  411               if( m.getDeclaringClass().isAssignableFrom( this.getClass()) ) {
  412                   m.invoke(this, new Object[] { value });
  413               } else {
  414                   m.invoke(resource, new Object[] { value });
  415               }
  416           } catch (InvocationTargetException e) {
  417               Throwable t = e.getTargetException();
  418               if (t == null)
  419                   t = e;
  420               if (t instanceof RuntimeException)
  421                   throw new RuntimeOperationsException
  422                       ((RuntimeException) t, "Exception invoking method " + name);
  423               else if (t instanceof Error)
  424                   throw new RuntimeErrorException
  425                       ((Error) t, "Error invoking method " + name);
  426               else
  427                   throw new MBeanException
  428                       (e, "Exception invoking method " + name);
  429           } catch (Exception e) {
  430               log.error("Exception invoking method " + name , e );
  431               throw new MBeanException
  432                   (e, "Exception invoking method " + name);
  433           }
  434           try {
  435               sendAttributeChangeNotification(new Attribute( name, oldValue),
  436                       attribute);
  437           } catch(Exception ex) {
  438               log.error("Error sending notification " + name, ex);
  439           }
  440           //attributes.put( name, value );
  441   //        if( source != null ) {
  442   //            // this mbean is asscoiated with a source - maybe we want to persist
  443   //            source.updateField(oname, name, value);
  444   //        }
  445       }
  446   
  447       public String toString() {
  448           if( resource==null ) 
  449               return "BaseModelMbean[" + resourceType + "]";
  450           return resource.toString();
  451       }
  452   
  453       /**
  454        * Set the values of several attributes of this MBean.
  455        *
  456        * @param attributes THe names and values to be set
  457        *
  458        * @return The list of attributes that were set and their new values
  459        */
  460       public AttributeList setAttributes(AttributeList attributes) {
  461           AttributeList response = new AttributeList();
  462   
  463           // Validate the input parameters
  464           if (attributes == null)
  465               return response;
  466           
  467           // Prepare and return our response, eating all exceptions
  468           String names[] = new String[attributes.size()];
  469           int n = 0;
  470           Iterator items = attributes.iterator();
  471           while (items.hasNext()) {
  472               Attribute item = (Attribute) items.next();
  473               names[n++] = item.getName();
  474               try {
  475                   setAttribute(item);
  476               } catch (Exception e) {
  477                   ; // Ignore all exceptions
  478               }
  479           }
  480   
  481           return (getAttributes(names));
  482   
  483       }
  484   
  485   
  486       // ----------------------------------------------------- ModelMBean Methods
  487   
  488   
  489       /**
  490        * Get the instance handle of the object against which we execute
  491        * all methods in this ModelMBean management interface.
  492        *
  493        * @exception InstanceNotFoundException if the managed resource object
  494        *  cannot be found
  495        * @exception MBeanException if the initializer of the object throws
  496        *  an exception
  497        * @exception RuntimeOperationsException if the managed resource or the
  498        *  resource type is <code>null</code> or invalid
  499        */
  500       public Object getManagedResource()
  501           throws InstanceNotFoundException, InvalidTargetObjectTypeException,
  502           MBeanException, RuntimeOperationsException {
  503   
  504           if (resource == null)
  505               throw new RuntimeOperationsException
  506                   (new IllegalArgumentException("Managed resource is null"),
  507                    "Managed resource is null");
  508   
  509           return resource;
  510   
  511       }
  512   
  513   
  514       /**
  515        * Set the instance handle of the object against which we will execute
  516        * all methods in this ModelMBean management interface.
  517        *
  518        * <strike>This method will detect and call "setModelMbean" method. A resource
  519        * can implement this method to get a reference to the model mbean.
  520        * The reference can be used to send notification and access the
  521        * registry.
  522        * </strike> The caller can provide the mbean instance or the object name to
  523        * the resource, if needed.
  524        *
  525        * @param resource The resource object to be managed
  526        * @param type The type of reference for the managed resource
  527        *  ("ObjectReference", "Handle", "IOR", "EJBHandle", or
  528        *  "RMIReference")
  529        *
  530        * @exception InstanceNotFoundException if the managed resource object
  531        *  cannot be found
  532        * @exception InvalidTargetObjectTypeException if this ModelMBean is
  533        *  asked to handle a reference type it cannot deal with
  534        * @exception MBeanException if the initializer of the object throws
  535        *  an exception
  536        * @exception RuntimeOperationsException if the managed resource or the
  537        *  resource type is <code>null</code> or invalid
  538        */
  539       public void setManagedResource(Object resource, String type)
  540           throws InstanceNotFoundException, 
  541           MBeanException, RuntimeOperationsException
  542       {
  543           if (resource == null)
  544               throw new RuntimeOperationsException
  545                   (new IllegalArgumentException("Managed resource is null"),
  546                    "Managed resource is null");
  547   
  548   //        if (!"objectreference".equalsIgnoreCase(type))
  549   //            throw new InvalidTargetObjectTypeException(type);
  550   
  551           this.resource = resource;
  552           this.resourceType = resource.getClass().getName();
  553           
  554   //        // Make the resource aware of the model mbean.
  555   //        try {
  556   //            Method m=resource.getClass().getMethod("setModelMBean",
  557   //                    new Class[] {ModelMBean.class});
  558   //            if( m!= null ) {
  559   //                m.invoke(resource, new Object[] {this});
  560   //            }
  561   //        } catch( NoSuchMethodException t ) {
  562   //            // ignore
  563   //        } catch( Throwable t ) {
  564   //            log.error( "Can't set model mbean ", t );
  565   //        }
  566       }
  567   
  568   
  569       // ------------------------------ ModelMBeanNotificationBroadcaster Methods
  570   
  571   
  572       /**
  573        * Add an attribute change notification event listener to this MBean.
  574        *
  575        * @param listener Listener that will receive event notifications
  576        * @param name Name of the attribute of interest, or <code>null</code>
  577        *  to indicate interest in all attributes
  578        * @param handback Handback object to be sent along with event
  579        *  notifications
  580        *
  581        * @exception IllegalArgumentException if the listener parameter is null
  582        */
  583       public void addAttributeChangeNotificationListener
  584           (NotificationListener listener, String name, Object handback)
  585           throws IllegalArgumentException {
  586   
  587           if (listener == null)
  588               throw new IllegalArgumentException("Listener is null");
  589           if (attributeBroadcaster == null)
  590               attributeBroadcaster = new BaseNotificationBroadcaster();
  591   
  592           if( log.isDebugEnabled() )
  593               log.debug("addAttributeNotificationListener " + listener);
  594   
  595           BaseAttributeFilter filter = new BaseAttributeFilter(name);
  596           attributeBroadcaster.addNotificationListener
  597               (listener, filter, handback);
  598   
  599       }
  600   
  601   
  602       /**
  603        * Remove an attribute change notification event listener from
  604        * this MBean.
  605        *
  606        * @param listener The listener to be removed
  607        * @param name The attribute name for which no more events are required
  608        *
  609        *
  610        * @exception ListenerNotFoundException if this listener is not
  611        *  registered in the MBean
  612        */
  613       public void removeAttributeChangeNotificationListener
  614           (NotificationListener listener, String name)
  615           throws ListenerNotFoundException {
  616   
  617           if (listener == null)
  618               throw new IllegalArgumentException("Listener is null");
  619           if (attributeBroadcaster == null)
  620               attributeBroadcaster = new BaseNotificationBroadcaster();
  621   
  622           // FIXME - currently this removes *all* notifications for this listener
  623           attributeBroadcaster.removeNotificationListener(listener);
  624   
  625       }
  626   
  627   
  628       /**
  629        * Remove an attribute change notification event listener from
  630        * this MBean.
  631        *
  632        * @param listener The listener to be removed
  633        * @param attributeName The attribute name for which no more events are required
  634        * @param handback Handback object to be sent along with event
  635        *  notifications
  636        *
  637        *
  638        * @exception ListenerNotFoundException if this listener is not
  639        *  registered in the MBean
  640        */
  641       public void removeAttributeChangeNotificationListener
  642           (NotificationListener listener, String attributeName, Object handback)
  643           throws ListenerNotFoundException {
  644   
  645           removeAttributeChangeNotificationListener(listener, attributeName);
  646   
  647       }
  648   
  649   
  650       /**
  651        * Send an <code>AttributeChangeNotification</code> to all registered
  652        * listeners.
  653        *
  654        * @param notification The <code>AttributeChangeNotification</code>
  655        *  that will be passed
  656        *
  657        * @exception MBeanException if an object initializer throws an
  658        *  exception
  659        * @exception RuntimeOperationsException wraps IllegalArgumentException
  660        *  when the specified notification is <code>null</code> or invalid
  661        */
  662       public void sendAttributeChangeNotification
  663           (AttributeChangeNotification notification)
  664           throws MBeanException, RuntimeOperationsException {
  665   
  666           if (notification == null)
  667               throw new RuntimeOperationsException
  668                   (new IllegalArgumentException("Notification is null"),
  669                    "Notification is null");
  670           if (attributeBroadcaster == null)
  671               return; // This means there are no registered listeners
  672           if( log.isDebugEnabled() )
  673               log.debug( "AttributeChangeNotification " + notification );
  674           attributeBroadcaster.sendNotification(notification);
  675   
  676       }
  677   
  678   
  679       /**
  680        * Send an <code>AttributeChangeNotification</code> to all registered
  681        * listeners.
  682        *
  683        * @param oldValue The original value of the <code>Attribute</code>
  684        * @param newValue The new value of the <code>Attribute</code>
  685        *
  686        * @exception MBeanException if an object initializer throws an
  687        *  exception
  688        * @exception RuntimeOperationsException wraps IllegalArgumentException
  689        *  when the specified notification is <code>null</code> or invalid
  690        */
  691       public void sendAttributeChangeNotification
  692           (Attribute oldValue, Attribute newValue)
  693           throws MBeanException, RuntimeOperationsException {
  694   
  695           // Calculate the class name for the change notification
  696           String type = null;
  697           if (newValue.getValue() != null)
  698               type = newValue.getValue().getClass().getName();
  699           else if (oldValue.getValue() != null)
  700               type = oldValue.getValue().getClass().getName();
  701           else
  702               return;  // Old and new are both null == no change
  703   
  704           AttributeChangeNotification notification =
  705               new AttributeChangeNotification
  706               (this, 1, System.currentTimeMillis(),
  707                "Attribute value has changed",
  708                oldValue.getName(), type,
  709                oldValue.getValue(), newValue.getValue());
  710           sendAttributeChangeNotification(notification);
  711   
  712       }
  713   
  714   
  715   
  716   
  717       /**
  718        * Send a <code>Notification</code> to all registered listeners as a
  719        * <code>jmx.modelmbean.general</code> notification.
  720        *
  721        * @param notification The <code>Notification</code> that will be passed
  722        *
  723        * @exception MBeanException if an object initializer throws an
  724        *  exception
  725        * @exception RuntimeOperationsException wraps IllegalArgumentException
  726        *  when the specified notification is <code>null</code> or invalid
  727        */
  728       public void sendNotification(Notification notification)
  729           throws MBeanException, RuntimeOperationsException {
  730   
  731           if (notification == null)
  732               throw new RuntimeOperationsException
  733                   (new IllegalArgumentException("Notification is null"),
  734                    "Notification is null");
  735           if (generalBroadcaster == null)
  736               return; // This means there are no registered listeners
  737           generalBroadcaster.sendNotification(notification);
  738   
  739       }
  740   
  741   
  742       /**
  743        * Send a <code>Notification</code> which contains the specified string
  744        * as a <code>jmx.modelmbean.generic</code> notification.
  745        *
  746        * @param message The message string to be passed
  747        *
  748        * @exception MBeanException if an object initializer throws an
  749        *  exception
  750        * @exception RuntimeOperationsException wraps IllegalArgumentException
  751        *  when the specified notification is <code>null</code> or invalid
  752        */
  753       public void sendNotification(String message)
  754           throws MBeanException, RuntimeOperationsException {
  755   
  756           if (message == null)
  757               throw new RuntimeOperationsException
  758                   (new IllegalArgumentException("Message is null"),
  759                    "Message is null");
  760           Notification notification = new Notification
  761               ("jmx.modelmbean.generic", this, 1, message);
  762           sendNotification(notification);
  763   
  764       }
  765   
  766   
  767   
  768   
  769       // ---------------------------------------- NotificationBroadcaster Methods
  770   
  771   
  772       /**
  773        * Add a notification event listener to this MBean.
  774        *
  775        * @param listener Listener that will receive event notifications
  776        * @param filter Filter object used to filter event notifications
  777        *  actually delivered, or <code>null</code> for no filtering
  778        * @param handback Handback object to be sent along with event
  779        *  notifications
  780        *
  781        * @exception IllegalArgumentException if the listener parameter is null
  782        */
  783       public void addNotificationListener(NotificationListener listener,
  784                                           NotificationFilter filter,
  785                                           Object handback)
  786           throws IllegalArgumentException {
  787   
  788           if (listener == null)
  789               throw new IllegalArgumentException("Listener is null");
  790   
  791           if( log.isDebugEnabled() ) log.debug("addNotificationListener " + listener);
  792   
  793           if (generalBroadcaster == null)
  794               generalBroadcaster = new BaseNotificationBroadcaster();
  795           generalBroadcaster.addNotificationListener
  796               (listener, filter, handback);
  797   
  798           // We'll send the attribute change notifications to all listeners ( who care )
  799           // The normal filtering can be used.
  800           // The problem is that there is no other way to add attribute change listeners
  801           // to a model mbean ( AFAIK ). I suppose the spec should be fixed.
  802           if (attributeBroadcaster == null)
  803               attributeBroadcaster = new BaseNotificationBroadcaster();
  804   
  805           if( log.isDebugEnabled() )
  806               log.debug("addAttributeNotificationListener " + listener);
  807   
  808           attributeBroadcaster.addNotificationListener
  809                   (listener, filter, handback);
  810       }
  811   
  812   
  813       /**
  814        * Return an <code>MBeanNotificationInfo</code> object describing the
  815        * notifications sent by this MBean.
  816        */
  817       public MBeanNotificationInfo[] getNotificationInfo() {
  818   
  819           // Acquire the set of application notifications
  820           MBeanNotificationInfo current[] = getMBeanInfo().getNotifications();
  821           if (current == null)
  822               current = new MBeanNotificationInfo[0];
  823           MBeanNotificationInfo response[] =
  824               new MBeanNotificationInfo[current.length + 2];
  825    //       Descriptor descriptor = null;
  826   
  827           // Fill in entry for general notifications
  828   //        descriptor = new DescriptorSupport
  829   //            (new String[] { "name=GENERIC",
  830   //                            "descriptorType=notification",
  831   //                            "log=T",
  832   //                            "severity=5",
  833   //                            "displayName=jmx.modelmbean.generic" });
  834           response[0] = new MBeanNotificationInfo
  835               (new String[] { "jmx.modelmbean.generic" },
  836                "GENERIC",
  837                "Text message notification from the managed resource");
  838                //descriptor);
  839   
  840           // Fill in entry for attribute change notifications
  841   //        descriptor = new DescriptorSupport
  842   //            (new String[] { "name=ATTRIBUTE_CHANGE",
  843   //                            "descriptorType=notification",
  844   //                            "log=T",
  845   //                            "severity=5",
  846   //                            "displayName=jmx.attribute.change" });
  847           response[1] = new MBeanNotificationInfo
  848               (new String[] { "jmx.attribute.change" },
  849                "ATTRIBUTE_CHANGE",
  850                "Observed MBean attribute value has changed");
  851                //descriptor);
  852   
  853           // Copy remaining notifications as reported by the application
  854           System.arraycopy(current, 0, response, 2, current.length);
  855           return (response);
  856   
  857       }
  858   
  859   
  860       /**
  861        * Remove a notification event listener from this MBean.
  862        *
  863        * @param listener The listener to be removed (any and all registrations
  864        *  for this listener will be eliminated)
  865        *
  866        * @exception ListenerNotFoundException if this listener is not
  867        *  registered in the MBean
  868        */
  869       public void removeNotificationListener(NotificationListener listener)
  870           throws ListenerNotFoundException {
  871   
  872           if (listener == null)
  873               throw new IllegalArgumentException("Listener is null");
  874           if (generalBroadcaster == null)
  875               generalBroadcaster = new BaseNotificationBroadcaster();
  876           generalBroadcaster.removeNotificationListener(listener);
  877   
  878   
  879       }
  880   
  881   
  882       /**
  883        * Remove a notification event listener from this MBean.
  884        *
  885        * @param listener The listener to be removed (any and all registrations
  886        *  for this listener will be eliminated)
  887        * @param handback Handback object to be sent along with event
  888        *  notifications
  889        *
  890        * @exception ListenerNotFoundException if this listener is not
  891        *  registered in the MBean
  892        */
  893       public void removeNotificationListener(NotificationListener listener,
  894                                              Object handback)
  895           throws ListenerNotFoundException {
  896   
  897           removeNotificationListener(listener);
  898   
  899       }
  900   
  901   
  902       /**
  903        * Remove a notification event listener from this MBean.
  904        *
  905        * @param listener The listener to be removed (any and all registrations
  906        *  for this listener will be eliminated)
  907        * @param filter Filter object used to filter event notifications
  908        *  actually delivered, or <code>null</code> for no filtering
  909        * @param handback Handback object to be sent along with event
  910        *  notifications
  911        *
  912        * @exception ListenerNotFoundException if this listener is not
  913        *  registered in the MBean
  914        */
  915       public void removeNotificationListener(NotificationListener listener,
  916                                              NotificationFilter filter,
  917                                              Object handback)
  918           throws ListenerNotFoundException {
  919   
  920           removeNotificationListener(listener);
  921   
  922       }
  923   
  924   
  925       // ------------------------------------------------ PersistentMBean Methods
  926   
  927   
  928       /**
  929        * Instantiates this MBean instance from data found in the persistent
  930        * store.  The data loaded could include attribute and operation values.
  931        * This method should be called during construction or initialization
  932        * of the instance, and before the MBean is registered with the
  933        * <code>MBeanServer</code>.
  934        *
  935        * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does
  936        * not support persistence.</p>
  937        *
  938        * @exception InstanceNotFoundException if the managed resource object
  939        *  cannot be found
  940        * @exception MBeanException if the initializer of the object throws
  941        *  an exception
  942        * @exception RuntimeOperationsException if an exception is reported
  943        *  by the persistence mechanism
  944        */
  945   //    public void load() throws InstanceNotFoundException,
  946   //        MBeanException, RuntimeOperationsException {
  947   //        // XXX If a context was set, use it to load the data
  948   //        throw new MBeanException
  949   //            (new IllegalStateException("Persistence is not supported"),
  950   //             "Persistence is not supported");
  951   //
  952   //    }
  953   
  954   
  955       /**
  956        * Capture the current state of this MBean instance and write it out
  957        * to the persistent store.  The state stored could include attribute
  958        * and operation values.  If one of these methods of persistence is not
  959        * supported, a "service not found" exception will be thrown.
  960        *
  961        * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation does
  962        * not support persistence.</p>
  963        *
  964        * @exception InstanceNotFoundException if the managed resource object
  965        *  cannot be found
  966        * @exception MBeanException if the initializer of the object throws
  967        *  an exception, or persistence is not supported
  968        * @exception RuntimeOperationsException if an exception is reported
  969        *  by the persistence mechanism
  970        */
  971   //    public void store() throws InstanceNotFoundException,
  972   //        MBeanException, RuntimeOperationsException {
  973   //
  974   //        // XXX if a context was set, use it to store the data
  975   //        throw new MBeanException
  976   //            (new IllegalStateException("Persistence is not supported"),
  977   //             "Persistence is not supported");
  978   //
  979   //    }
  980   
  981       // --------------------  BaseModelMBean methods --------------------
  982   
  983       /** Set the type of the mbean. This is used as a key to locate
  984        * the description in the Registry.
  985        *
  986        * @param type the type of classname of the modeled object
  987        */
  988   //    void setModeledType( String type ) {
  989   //        initModelInfo(type);
  990   //        createResource();
  991   //    }
  992       /** Set the type of the mbean. This is used as a key to locate
  993        * the description in the Registry.
  994        *
  995        * @param type the type of classname of the modeled object
  996        */
  997   //    void initModelInfo( String type ) {
  998   //        try {
  999   //            if( log.isDebugEnabled())
 1000   //                log.debug("setModeledType " + type);
 1001   //
 1002   //            log.debug( "Set model Info " + type);
 1003   //            if(type==null) {
 1004   //                return;
 1005   //            }
 1006   //            resourceType=type;
 1007   //            //Thread.currentThread().setContextClassLoader(BaseModelMBean.class.getClassLoader());
 1008   //            Class c=null;
 1009   //            try {
 1010   //                c=Class.forName( type);
 1011   //            } catch( Throwable t ) {
 1012   //                log.debug( "Error creating class " + t);
 1013   //            }
 1014   //
 1015   //            // The class c doesn't need to exist
 1016   //            ManagedBean descriptor=getRegistry().findManagedBean(c, type);
 1017   //            if( descriptor==null ) 
 1018   //                return;
 1019   //            this.setModelMBeanInfo(descriptor.createMBeanInfo());
 1020   //        } catch( Throwable ex) {
 1021   //            log.error( "TCL: " + Thread.currentThread().getContextClassLoader(),
 1022   //                    ex);
 1023   //        }
 1024   //    }
 1025   
 1026       /** Set the type of the mbean. This is used as a key to locate
 1027        * the description in the Registry.
 1028        */
 1029   //    protected void createResource() {
 1030   //        try {
 1031   //            //Thread.currentThread().setContextClassLoader(BaseModelMBean.class.getClassLoader());
 1032   //            Class c=null;
 1033   //            try {
 1034   //                c=Class.forName( resourceType );
 1035   //                resource = c.newInstance();
 1036   //            } catch( Throwable t ) {
 1037   //                log.error( "Error creating class " + t);
 1038   //            }
 1039   //        } catch( Throwable ex) {
 1040   //            log.error( "TCL: " + Thread.currentThread().getContextClassLoader(),
 1041   //                    ex);
 1042   //        }
 1043   //    }
 1044   
 1045   
 1046       public String getModelerType() {
 1047           return resourceType;
 1048       }
 1049   
 1050       public String getClassName() {
 1051           return getModelerType();
 1052       }
 1053   
 1054       public ObjectName getJmxName() {
 1055           return oname;
 1056       }
 1057   
 1058       public String getObjectName() {
 1059           if (oname != null) {
 1060               return oname.toString();
 1061           } else {
 1062               return null;
 1063           }
 1064       }
 1065   
 1066   //    public void setRegistry(Registry registry) {
 1067   //        this.registry = registry;
 1068   //    }
 1069   //
 1070   //    public Registry getRegistry() {
 1071   //        // XXX Need a better solution - to avoid the static
 1072   //        if( registry == null )
 1073   //            registry=Registry.getRegistry();
 1074   //
 1075   //        return registry;
 1076   //    }
 1077   
 1078       // ------------------------------------------------------ Protected Methods
 1079   
 1080   
 1081       /**
 1082        * Create and return a default <code>ModelMBeanInfo</code> object.
 1083        */
 1084   //    protected ModelMBeanInfo createDefaultModelMBeanInfo() {
 1085   //
 1086   //        return (new ModelMBeanInfoSupport(this.getClass().getName(),
 1087   //                                          "Default ModelMBean",
 1088   //                                          null, null, null, null));
 1089   //
 1090   //    }
 1091   
 1092       /**
 1093        * Is the specified <code>ModelMBeanInfo</code> instance valid?
 1094        *
 1095        * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation
 1096        * does not check anything, but this method can be overridden
 1097        * as required.</p>
 1098        *
 1099        * @param info The <code>ModelMBeanInfo object to check
 1100        */
 1101   //    protected boolean isModelMBeanInfoValid(ModelMBeanInfo info) {
 1102   //        return (true);
 1103   //    }
 1104   
 1105       // -------------------- Registration  --------------------
 1106       // XXX We can add some method patterns here- like setName() and
 1107       // setDomain() for code that doesn't implement the Registration
 1108   
 1109       public ObjectName preRegister(MBeanServer server,
 1110                                     ObjectName name)
 1111               throws Exception
 1112       {
 1113           if( log.isDebugEnabled())
 1114               log.debug("preRegister " + resource + " " + name );
 1115           oname=name;
 1116           if( resource instanceof MBeanRegistration ) {
 1117               oname = ((MBeanRegistration)resource).preRegister(server, name );
 1118           }
 1119           return oname;
 1120       }
 1121   
 1122       public void postRegister(Boolean registrationDone) {
 1123           if( resource instanceof MBeanRegistration ) {
 1124               ((MBeanRegistration)resource).postRegister(registrationDone);
 1125           }
 1126       }
 1127   
 1128       public void preDeregister() throws Exception {
 1129           if( resource instanceof MBeanRegistration ) {
 1130               ((MBeanRegistration)resource).preDeregister();
 1131           }
 1132       }
 1133   
 1134       public void postDeregister() {
 1135           if( resource instanceof MBeanRegistration ) {
 1136               ((MBeanRegistration)resource).postDeregister();
 1137           }
 1138       }
 1139   
 1140       static class MethodKey {
 1141   	private String name;
 1142   	private String[] signature;
 1143   
 1144   	MethodKey(String name, String[] signature) {
 1145   	    this.name = name;
 1146   	    if(signature == null) {
 1147   		signature = new String[0];
 1148   	    }
 1149   	    this.signature = signature;
 1150   	}
 1151   
 1152   	public boolean equals(Object other) {
 1153   	    if(!(other instanceof MethodKey)) {
 1154   		return false;
 1155   	    }
 1156   	    MethodKey omk = (MethodKey)other;
 1157   	    if(!name.equals(omk.name)) {
 1158   		return false;
 1159   	    }
 1160   	    if(signature.length != omk.signature.length) {
 1161   		return false;
 1162   	    }
 1163   	    for(int i=0; i < signature.length; i++) {
 1164   		if(!signature[i].equals(omk.signature[i])) {
 1165   		    return false;
 1166   		}
 1167   	    }
 1168   	    return true;
 1169   	}
 1170   
 1171   	public int hashCode() {
 1172   	    return name.hashCode();
 1173   	}
 1174       }
 1175   }

Home » apache-tomcat-6.0.26-src » org.apache » tomcat » util » modeler » [javadoc | source]