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

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