cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From giac...@apache.org
Subject svn commit: r367400 - in /cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon: components/flow/ core/container/handler/ util/ util/jmx/
Date Mon, 09 Jan 2006 21:29:25 GMT
Author: giacomo
Date: Mon Jan  9 13:29:16 2006
New Revision: 367400

URL: http://svn.apache.org/viewcvs?rev=367400&view=rev
Log:
some improvements on JMX. Need to get this in a long as I have a change to get it right

Added:
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/flow/mbean.properties
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandlerObserver.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/mbean.properties
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/ModelMBeanImpl.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/TypeUtil.java
Removed:
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/flow/ContinuationsManagerImplMBean.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandlerMBean.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/SingleThreadedComponentHandlerMBean.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/JMXUtils.java
Modified:
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/NonThreadSafePoolableComponentHandler.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandler.java

Added: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/flow/mbean.properties
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/flow/mbean.properties?rev=367400&view=auto
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/flow/mbean.properties (added)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/flow/mbean.properties Mon Jan  9 13:29:16 2006
@@ -0,0 +1,6 @@
+ContinuationsManagerImpl = Manages the Continuations
+
+ContinuationsManagerImpl.defaultTimeToLive = How many milliseconds a continuation can live by default
+ContinuationsManagerImpl.bindContinuationsToSession = Whether Continuations will be bind to the Http Session
+ContinuationsManagerImpl.expirationCheckInterval = The expiration check interval in milliseconds
+ContinuationsManagerImpl.expirationSet = The set of expirations of Continuations
\ No newline at end of file

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/NonThreadSafePoolableComponentHandler.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/NonThreadSafePoolableComponentHandler.java?rev=367400&r1=367399&r2=367400&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/NonThreadSafePoolableComponentHandler.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/NonThreadSafePoolableComponentHandler.java Mon Jan  9 13:29:16 2006
@@ -254,7 +254,7 @@
     /**
      * @return Returns the max.
      */
-    protected int getMax()
+    public int getMax()
     {
         return max;
     }
@@ -262,7 +262,7 @@
     /**
      * @return Returns the readySize.
      */
-    protected int getReadySize()
+    public int getReadySize()
     {
         return readySize;
     }
@@ -270,7 +270,7 @@
     /**
      * @return Returns the size.
      */
-    protected int getSize()
+    public int getSize()
     {
         return size;
     }
@@ -278,7 +278,7 @@
     /**
      * @return Returns the highWaterMark.
      */
-    protected int getHighWaterMark()
+    public int getHighWaterMark()
     {
         return highWaterMark;
     }

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandler.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandler.java?rev=367400&r1=367399&r2=367400&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandler.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandler.java Mon Jan  9 13:29:16 2006
@@ -40,7 +40,7 @@
 extends NonThreadSafePoolableComponentHandler {
     
     /** All the interfaces for the proxy */
-    protected final Class[] interfaces;
+    private final Class[] interfaces;
     
     /**
      * Create a PoolableComponentHandler which manages a pool of Components
@@ -120,6 +120,14 @@
             workInterfaces.add( interfaces[i] );
             this.addInterfaces(interfaces[i].getInterfaces(), workInterfaces);
         }
+    }
+
+    /**
+     * @return Returns the interfaces.
+     */
+    public Class[] getInterfaces()
+    {
+        return interfaces;
     }
 
     protected static final class ProxyHandler implements InvocationHandler, Core.CleanupTask {

Added: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandlerObserver.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandlerObserver.java?rev=367400&view=auto
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandlerObserver.java (added)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/PoolableComponentHandlerObserver.java Mon Jan  9 13:29:16 2006
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.core.container.handler;
+
+import org.apache.cocoon.util.jmx.ModelMBeanImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.MBeanOperationInfo;
+import javax.management.ObjectName;
+
+
+/**
+ * This MBean creates and registers a GaugeMonitor for every PoolableComponentHandler added
+ */
+public class PoolableComponentHandlerObserver
+    extends ModelMBeanImpl {
+    //~ Static fields/initializers ----------------------------------------------------------------------
+
+    /** Suffix to add to base ObjectName */
+    public static final String JMX_OBJECTNAME_SUFFIX = "type=pool-observer";
+
+    /** JMX Attribute name */
+    public static final String JMX_ATTR_EXHAUSTED_POOLS = "exhaustedPools";
+
+    /** JMX Attribute name */
+    public static final String JMX_ATTR_NUMOF_EXHAUSTED_POOLS = "numberOfExhaustedPools";
+
+    /** JMX Operation name */
+    public static final String JMX_OP_RESET_HIGH_WATER_MARKS = "resetHighWaterMarks";
+
+    //~ Instance fields ---------------------------------------------------------------------------------
+
+    /** The list of PoolableComponentHandlerMBeans ObjectName to observe */
+    private List handlerMBeans = new ArrayList();
+
+    /** The list of PoolableComponentHandlers to observe */
+    private List handlers = new ArrayList();
+
+    //~ Constructors ------------------------------------------------------------------------------------
+
+    /**
+     * Creates a new PoolableComponentHandlerMonitorMBean object.
+     */
+    public PoolableComponentHandlerObserver() {
+        super();
+        defineManagedResource();
+    }
+
+    //~ Methods -----------------------------------------------------------------------------------------
+
+    /**
+     * Returns the array of JMX ObjectName of exhausted pools
+     *
+     * @return array of JMX ObjectName
+     */
+    public ObjectName[] getExhaustedPools() {
+        final List exhaustedPools = getExhaustedPoolList();
+
+        return (ObjectName[])exhaustedPools.toArray(new ObjectName[exhaustedPools.size()]);
+    }
+
+    /**
+     * Returns the array of JMX ObjectName of exhausted pools
+     *
+     * @return array of JMX ObjectName
+     */
+    public int getNumberOfExhaustedPools() {
+        final List exhaustedPools = getExhaustedPoolList();
+
+        return exhaustedPools.size();
+    }
+
+    /**
+     * Add a PoolableComponentHandler to be monitored
+     *
+     * @param handler The PoolableComponentHandler to add
+     * @param handlerName it's JMX ObjectName
+     */
+    protected synchronized void addPoolHandler(final PoolableComponentHandler handler,
+                                               final ObjectName handlerName) {
+        if(this.handlers.contains(handler)) {
+            return;
+        }
+
+        this.handlers.add(handler);
+        this.handlerMBeans.add(handlerName);
+    }
+
+    /**
+     * Define the JMX interface
+     */
+    protected void defineManagedResource() {
+        super.defineManagedResource();
+        defineAttribute(JMX_ATTR_EXHAUSTED_POOLS, false, true);
+        defineAttribute(JMX_ATTR_NUMOF_EXHAUSTED_POOLS, false, true);
+        defineOperation(JMX_OP_RESET_HIGH_WATER_MARKS, MBeanOperationInfo.INFO);
+    }
+
+    /**
+     * Returns the list JMX ObjectName of exhausted pools
+     *
+     * @return list of JMX ObjectName
+     */
+    private List getExhaustedPoolList() {
+        final List exhaustedPools = new ArrayList();
+
+        for(int i = 0; i < this.handlers.size(); i++) {
+            final PoolableComponentHandler handler = (PoolableComponentHandler)this.handlers.get(i);
+
+            if((handler.getHighWaterMark() - handler.getMax()) > 0) {
+                exhaustedPools.add(this.handlerMBeans.get(i));
+            }
+        }
+
+        return exhaustedPools;
+    }
+}

Added: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/mbean.properties
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/mbean.properties?rev=367400&view=auto
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/mbean.properties (added)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/core/container/handler/mbean.properties Mon Jan  9 13:29:16 2006
@@ -0,0 +1,23 @@
+SingleThreadedComponentHandler = Handles Creation/Decomission of single threaded Components
+
+SingleThreadedComponentHandler.maxCreated = The current numbers of Components created
+SingleThreadedComponentHandler.maxDecommissioned = The current numbers of Components Decomissioned
+SingleThreadedComponentHandler.outstanding = Number of Components theoretically in use
+
+
+PoolableComponentHandler = Manages Pools of Components
+
+PoolableComponentHandler.interfaces = The Array of Interfaces the managed Components have
+PoolableComponentHandler.defaultMaxPoolSize = The Default maximum pool size
+PoolableComponentHandler.maxPoolSize = The configured maximum pool size
+PoolableComponentHandler.readyPoolSize = The number of Components ready to be used
+PoolableComponentHandler.totalPoolSize = The total number of Components in the pool
+PoolableComponentHandler.highWaterMark = The high water mark of Components created
+PoolableComponentHandler.role = The role name of the Component managed by his pool
+
+
+PoolableComponentHandlerObserver = Monitors the pool sizes
+
+PoolableComponentHandlerObserver.exhaustedPools = Pools that have exhausted
+PoolableComponentHandlerObserver.numberOfExhaustedPools = Number of pools that have exhausted
+PoolableComponentHandlerObserver.resetHighWaterMarks = Reset all high water marks
\ No newline at end of file

Added: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/ModelMBeanImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/ModelMBeanImpl.java?rev=367400&view=auto
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/ModelMBeanImpl.java (added)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/ModelMBeanImpl.java Mon Jan  9 13:29:16 2006
@@ -0,0 +1,1263 @@
+// ========================================================================
+// $Id: ModelMBeanImpl.java,v 1.17 2005/05/12 12:46:25 gregwilkins Exp $
+// Copyright 1999-2004 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at 
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================================================================
+
+// This class was originally developed by the Jetty project
+
+package org.apache.cocoon.util.jmx;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import javax.management.Attribute;
+import javax.management.AttributeChangeNotification;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeOperationsException;
+import javax.management.modelmbean.InvalidTargetObjectTypeException;
+import javax.management.modelmbean.ModelMBean;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+import javax.management.modelmbean.ModelMBeanNotificationInfo;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/* ------------------------------------------------------------ */
+/** Model MBean Implementation.
+ * This implementation of the JMX Model MBean API is designed to allow
+ * easy creation of Model MBeans. From minimal descriptions of
+ * operations and attributes, reflection is used to determine the full
+ * signature and ResourceBundles are used to determine other meta data.
+ *
+ * This class is normally used in one of the following patterns:<UL>
+ * <LI>As a base class for a real MBean that contains the actual
+ * attributes and operations of the MBean.  Such an Object is only
+ * usable in a JMX environment.
+ * <LI>As a proxy MBean to another non-JMX object. The attributes and
+ * operations of the proxied object are defined in the MBean.  This
+ * pattern is used when an existing non-JMX objects API is to be
+ * exposed as an MBean.
+ * <LI>As a base class for a proxy MBean. The attributes and oepration
+ * of the MBean are implemented by the derived class but delegate to
+ * one or more other objects. This pattern is used if existing objects
+ * are to be managed by JMX, but a new management API needs to be
+ * defined.
+ * </UL>
+ *
+ * @version $Revision: 1.17 $
+ */
+public class ModelMBeanImpl
+    implements ModelMBean,
+               MBeanRegistration
+{
+    private static Log log = LogFactory.getLog(ModelMBeanImpl.class);
+
+    public final static int IMPACT_ACTION = MBeanOperationInfo.ACTION;
+    public final static int IMPACT_ACTION_INFO = MBeanOperationInfo.ACTION_INFO;
+    public final static int IMPACT_INFO = MBeanOperationInfo.INFO;
+    public final static int IMPACT_UNKOWN = MBeanOperationInfo.UNKNOWN;
+
+    public final static String STRING="java.lang.String";
+    public final static String OBJECT="java.lang.Object";
+    public final static String INT="int";
+    
+    public final static String[] NO_PARAMS=new String[0];
+
+    public final static boolean READ_WRITE=true;
+    public final static boolean READ_ONLY=false;
+    public final static boolean ON_MBEAN=true;
+    public final static boolean ON_OBJECT=false;
+    
+    
+    private static HashMap __objectId = new HashMap();
+
+    private static String __defaultDomain="org.mortbay";
+    
+    protected ModelMBeanInfoSupport _beanInfo;
+    private MBeanServer _mBeanServer;
+    private Object _object;
+    private ObjectName _objectName;
+    
+    private boolean _dirty=false;
+    private HashMap _getter = new HashMap(4);
+    private HashMap _setter = new HashMap(4);
+    private HashMap _method = new HashMap(4);
+    private ArrayList _attributes = new ArrayList(4);
+    private ArrayList _operations = new ArrayList(4);
+    private ArrayList _notifications = new ArrayList(4);
+    private String _baseObjectName=null;
+    private Map _components = new HashMap(4);
+
+    /* ------------------------------------------------------------ */
+    /* ------------------------------------------------------------ */
+    /** Create MBean for Object.
+     * Attempts to create an MBean for the object by searching the
+     * package and class name space.  For example an object of the
+     * type <PRE>
+     *   class com.acme.MyClass extends com.acme.util.BaseClass
+     * </PRE>
+     * Then this method would look for the following
+     * classes:<UL>
+     * <LI>com.acme.MyClassMBean
+     * <LI>com.acme.jmx.MyClassMBean
+     * <LI>com.acme.util.BaseClassMBean
+     * <LI>com.acme.util.jmx.BaseClassMBean
+     * </UL>
+     * @param o The object
+     * @return A new instance of an MBean for the object or null.
+     */
+    public static ModelMBean mbeanFor(Object o)
+    {
+        try
+        {
+            Class oClass = o.getClass();
+            ClassLoader loader =oClass.getClassLoader();
+
+            ModelMBean mbean = null;
+            boolean jmx=false;
+            Class[] interfaces=null;
+            int i=0;
+            
+            while (mbean==null && oClass!=null)
+            {
+                Class focus=interfaces==null?oClass:interfaces[i];
+                String pName = focus.getPackage().getName();
+                String cName = focus.getName().substring(pName.length()+1);
+                String mName=pName+(jmx?".jmx.":".")+cName+"MBean";
+
+                try{
+                    Class mClass=loader.loadClass(mName);
+                    mbean=(ModelMBean)mClass.newInstance();
+                    mbean.setManagedResource(o,"objectReference");
+                    return mbean;
+                }
+                catch(ClassNotFoundException e)
+                {
+                    if (!e.toString().endsWith("MBean")) {
+                        log.warn("Cannot find class ending in MBean for " + oClass.getName(),e);
+                    }
+                }
+                catch(Error e)
+                {
+                    log.warn("Error raised when creating class " + mName,e);
+                    mbean=null;
+                }
+                catch(Exception e)
+                {
+                    log.warn("Exception raised when creating class " + mName,e);
+                    mbean=null;
+                }
+
+                if (jmx)
+                {
+                    if (interfaces!=null)
+                    {
+                        i++;
+                        if (i>=interfaces.length)
+                        {
+                            interfaces=null;
+                            oClass=oClass.getSuperclass();
+                        }
+                    }
+                    else
+                    {
+                        interfaces=oClass.getInterfaces();
+                        i=0;
+                        if (interfaces==null || interfaces.length==0)
+                        {
+                            interfaces=null;
+                            oClass=oClass.getSuperclass();
+                        }
+                    }
+                }
+                jmx=!jmx;
+            }
+        }
+        catch(Exception e)
+        {
+            if(log.isDebugEnabled()) {
+                log.debug("Exception raised during MBean building for " + o.getClass().getName(), e);
+            }
+        }
+        return null;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** MBean Constructor.
+     * No proxy object is defined.  Attributes and operations are
+     * defined on this instance. 
+     */
+    public ModelMBeanImpl()
+    {}
+    
+    /* ------------------------------------------------------------ */
+    /** Proxy MBean Constructor. 
+     * @param proxyObject The actual object on which attributes and
+     * operations are to be defined and called. 
+     */
+    public ModelMBeanImpl(Object proxyObject)
+    {
+        try
+        {
+            setManagedResource(proxyObject,"objectReference");
+        }
+        catch(Exception e)
+        {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+    
+    
+    /* ------------------------------------------------------------ */
+    public static String getDefaultDomain()    { return __defaultDomain; }
+    
+    /* ------------------------------------------------------------ */
+    public static void setDefaultDomain(String d)   { __defaultDomain=d; }
+    
+    /* ------------------------------------------------------------ */
+    public MBeanServer getMBeanServer()       { return _mBeanServer; }
+
+    /* ------------------------------------------------------------ */
+    public ObjectName getObjectName()          { return _objectName; }
+    
+    /* ------------------------------------------------------------ */
+    public Object getManagedResource()             { return _object; }
+  
+    /* ------------------------------------------------------------ */
+    public void setManagedResource(Object proxyObject, String type)
+        throws MBeanException,
+               RuntimeOperationsException,
+               InstanceNotFoundException,
+               InvalidTargetObjectTypeException
+    {
+        if (proxyObject==null)
+        {
+            proxyObject=null;
+            return;
+        }
+        
+        log.debug("setManagedResource");
+        if (!"objectreference".equalsIgnoreCase(type))
+            throw new InvalidTargetObjectTypeException(type);
+
+        if (_object==null)
+        {
+            // first set so define attributes etc.
+            _object=proxyObject;
+            
+            defineManagedResource();
+        }
+        else
+            _object=proxyObject;    
+    }
+
+    /* ------------------------------------------------------------ */
+    /** Define the Managed Resource.
+     * This method is called the first time setManagedResource is
+     * called with a non-null object. It should be implemented by a
+     * derived ModelMBean to define the attributes and operations
+     * after an initial object has been set.
+     */
+    protected void defineManagedResource()
+    {}
+    
+    /* ------------------------------------------------------------ */
+    /** Not Supported.
+     * Use RequiredModelMBean for this style of MBean creation.
+     */
+    public void setModelMBeanInfo(ModelMBeanInfo info)
+        throws MBeanException,
+               RuntimeOperationsException
+    {
+        throw new Error("setModelMBeanInfo not supported");
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Define an attribute on the managed object.
+     * The meta data is defined by looking for standard getter and
+     * setter methods. Descriptions are obtained with a call to
+     * findDescription with the attribute name.
+     * @param name The name of the attribute. Normal java bean
+     * capitlization is enforced on this name.
+     */
+    public synchronized void defineAttribute(String name)
+    {
+        defineAttribute(name,true,false);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Define an attribute on the managed object.
+     * The meta data is defined by looking for standard getter and
+     * setter methods. Descriptions are obtained with a call to
+     * findDescription with the attribute name.
+     * @param name The name of the attribute. Normal java bean
+     * capitlization is enforced on this name.
+     * @param writable If false, do not look for a setter.
+     */
+    public synchronized void defineAttribute(String name, boolean writable)
+    {
+        defineAttribute(name,writable,false);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Define an attribute on the managed object.
+     * The meta data is defined by looking for standard getter and
+     * setter methods. Descriptions are obtained with a call to
+     * findDescription with the attribute name.
+     * @param name The name of the attribute. Normal java bean
+     * capitlization is enforced on this name.
+     * @param writable If false, do not look for a setter.
+     * @param onMBean .
+     */
+    public synchronized void defineAttribute(String name,
+                                             boolean writable,
+                                             boolean onMBean)
+    {
+        _dirty=true;
+        
+        String uName=name.substring(0,1).toUpperCase()+name.substring(1);
+        name=java.beans.Introspector.decapitalize(name);
+        Class oClass=onMBean?this.getClass():_object.getClass();
+
+        Class type=null;
+        Method getter=null;
+        Method setter=null;
+        Method[] methods=oClass.getMethods();
+        for (int m=0;m<methods.length;m++)
+        {
+            if ((methods[m].getModifiers()&Modifier.PUBLIC)==0)
+                continue;
+
+            // Look for a getter
+            if (methods[m].getName().equals("get"+uName) &&
+                methods[m].getParameterTypes().length==0)
+            {
+                if (getter!=null)
+                    throw new IllegalArgumentException("Multiple getters for attr "+name);
+                getter=methods[m];
+                if (type!=null &&
+                    !type.equals(methods[m].getReturnType()))
+                    throw new IllegalArgumentException("Type conflict for attr "+name);
+                type=methods[m].getReturnType();
+            }
+
+            // Look for an is getter
+            if (methods[m].getName().equals("is"+uName) &&
+                methods[m].getParameterTypes().length==0)
+            {
+                if (getter!=null)
+                    throw new IllegalArgumentException("Multiple getters for attr "+name);
+                getter=methods[m];
+                if (type!=null &&
+                    !type.equals(methods[m].getReturnType()))
+                    throw new IllegalArgumentException("Type conflict for attr "+name);
+                type=methods[m].getReturnType();
+            }
+
+            // look for a setter
+            if (writable &&
+                methods[m].getName().equals("set"+uName) &&
+                methods[m].getParameterTypes().length==1)
+            {
+                if (setter!=null)
+                    throw new IllegalArgumentException("Multiple setters for attr "+name);
+                setter=methods[m];
+                if (type!=null &&
+                    !type.equals(methods[m].getParameterTypes()[0]))
+                    throw new IllegalArgumentException("Type conflict for attr "+name);
+                type=methods[m].getParameterTypes()[0];
+            }
+        }
+
+        if (getter==null && setter==null)
+            throw new IllegalArgumentException("No getter or setters found for "+name);
+        
+        try
+        {
+            // Remember the methods
+            _getter.put(name,getter);
+            _setter.put(name,setter);
+            // create and add the info
+            _attributes.add(new ModelMBeanAttributeInfo(name,
+                                                        findDescription(name),
+                                                        getter,
+                                                        setter));
+        }
+        catch(Exception e)
+        {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+
+    /* ------------------------------------------------------------ */
+    /** Define an attribute.
+     * Explicit definition of an attribute. Reflection is used to
+     * locate the actual getter and setter methods.
+     * @param attrInfo ModelMBeanAttributeInfo.
+     */
+    public synchronized void defineAttribute(ModelMBeanAttributeInfo attrInfo)
+    {
+        if (_object==null)
+            throw new IllegalStateException("No Object");
+        
+        _dirty=true;
+        
+        String name=attrInfo.getName();
+        String uName=name.substring(0,1).toUpperCase()+name.substring(1);
+        Class oClass=_object.getClass();
+
+        try
+        {
+            Class type=TypeUtil.fromName(attrInfo.getType());
+            if (type==null)
+                type=Thread.currentThread().getContextClassLoader().loadClass(attrInfo.getType());
+        
+            Method getter=null;
+            Method setter=null;
+            
+            if (attrInfo.isReadable())
+                getter=oClass.getMethod((attrInfo.isIs()?"is":"get")+uName,(java.lang.Class[])null);
+            
+            if (attrInfo.isWritable())
+                setter=oClass.getMethod("set"+uName,new Class[] {type});
+            
+            _getter.put(name,getter);
+            _setter.put(name,setter);
+            _attributes.add(attrInfo);
+        }
+        catch(Exception e)
+        {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Define an operation on the managed object.
+     * Defines an operation with no parameters. Refection is used to
+     * determine the return type and the description is found with a
+     * call to findDescription on "name()".
+     * @param name  Name of the method call
+     * @param impact Impact as defined in MBeanOperationInfo
+     */
+    public synchronized void defineOperation(String name,int impact)
+    {
+        defineOperation(name,null,impact,false);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Define an operation on the managed object.
+     * Defines an operation with parameters. Refection is used to
+     * determine find the method and it's return type. The description
+     * of the method is found with a call to findDescription on
+     * "name(signature)". The name and description of each parameter
+     * is found with a call to findDescription with
+     * "name(partialSignature", the returned description is for the
+     * last parameter of the partial signature and is assumed to start
+     * with the parameter name, followed by a colon.
+     * @param name The name of the method call.
+     * @param signature The types of the operation parameters.
+     * @param impact Impact as defined in MBeanOperationInfo
+     */
+    public synchronized void defineOperation(String name,
+                                             String[] signature,
+                                             int impact)
+    {
+        defineOperation(name,signature,impact,false);
+    }
+        
+    /* ------------------------------------------------------------ */
+    /** Define an operation on the managed object.
+     * Defines an operation with parameters. Refection is used to
+     * determine find the method and it's return type. The description
+     * of the method is found with a call to findDescription on
+     * "name(signature)". The name and description of each parameter
+     * is found with a call to findDescription with
+     * "name(partialSignature", the returned description is for the
+     * last parameter of the partial signature and is assumed to start
+     * with the parameter name, followed by a colon.
+     * @param name The name of the method call.
+     * @param signature The types of the operation parameters.
+     * @param impact Impact as defined in MBeanOperationInfo
+     * @param onMBean true if the operation is defined on the mbean
+     */
+    public synchronized void defineOperation(String name,
+            String[] signature,
+            int impact,
+            boolean onMBean)
+    {
+        _dirty=true;        
+        Class oClass=onMBean?this.getClass():_object.getClass();
+        if (signature==null) signature=new String[0];
+
+        try
+        {
+            Class[] types = new Class[signature.length];
+            MBeanParameterInfo[] pInfo = new
+                MBeanParameterInfo[signature.length];
+
+            // Check types and build methodKey
+            String methodKey=name+"(";
+            for (int i=0;i<signature.length;i++)
+            {
+                Class type=TypeUtil.fromName(signature[i]);
+                if (type==null)
+                    type=Thread.currentThread().getContextClassLoader().loadClass(signature[i]);
+                types[i]=type;
+                signature[i]=type.isPrimitive()?TypeUtil.toName(type):signature[i];
+                methodKey+=(i>0?",":"")+signature[i];
+            }
+            methodKey+=")";
+
+            // Build param infos
+            for (int i=0;i<signature.length;i++)
+            {
+                String description=findDescription(methodKey+"["+i+"]");
+                int colon=description.indexOf(":");
+                if (colon<0)
+                {
+                    description="param"+i+":"+description;
+                    colon=description.indexOf(":");
+                }
+                pInfo[i]=new
+                    MBeanParameterInfo(description.substring(0,colon).trim(),
+                                       signature[i],
+                                       description.substring(colon+1).trim());
+            }
+
+            // build the operation info
+            Method method=oClass.getMethod(name,types);
+            Class returnClass=method.getReturnType();
+            _method.put(methodKey,method);
+            _operations.add(new ModelMBeanOperationInfo
+                (name,
+                 findDescription(methodKey),
+                 pInfo,
+                 returnClass.isPrimitive()?TypeUtil.toName(returnClass):(returnClass.getName()),
+                 impact));
+        }
+        catch(Exception e)
+        {
+            log.warn("operation "+name,e);
+            throw new IllegalArgumentException(e.toString());
+        }
+        
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Define an operation.
+     * Explicit definition of an operation. Reflection is used to
+     * locate method called.
+     * @param opInfo 
+     */
+    public synchronized void defineOperation(ModelMBeanOperationInfo opInfo)
+    {
+        _dirty=true;        
+        Class oClass=_object.getClass();
+        
+        try
+        {
+            MBeanParameterInfo[] pInfo = opInfo.getSignature();
+            
+            Class[] types = new Class[pInfo.length];
+            String method=opInfo.getName()+"(";
+            for (int i=0;i<pInfo.length;i++)
+            {
+                Class type=TypeUtil.fromName(pInfo[i].getType());
+                if (type==null)
+                    type=Thread.currentThread().getContextClassLoader().loadClass(pInfo[i].getType());
+                types[i]=type;
+                method+=(i>0?",":"")+pInfo[i].getType();
+            }
+            method+=")";
+
+            _method.put(method,oClass.getMethod(opInfo.getName(),types));
+            _operations.add(opInfo);
+        }
+        catch(Exception e)
+        {
+            throw new IllegalArgumentException(e.toString());
+        }   
+    }
+    
+    /* ------------------------------------------------------------ */
+    public synchronized MBeanInfo getMBeanInfo()
+    {
+        log.debug("getMBeanInfo");
+
+        if (_dirty)
+        {
+            _dirty=false;
+            ModelMBeanAttributeInfo[] attributes = (ModelMBeanAttributeInfo[])
+                _attributes.toArray(new ModelMBeanAttributeInfo[_attributes.size()]);
+            ModelMBeanOperationInfo[] operations = (ModelMBeanOperationInfo[])
+                _operations.toArray(new ModelMBeanOperationInfo[_operations.size()]);
+            ModelMBeanNotificationInfo[] notifications =(ModelMBeanNotificationInfo[])
+                _notifications.toArray(new ModelMBeanNotificationInfo[_notifications.size()]);
+
+            _beanInfo =
+                new ModelMBeanInfoSupport(_object.getClass().getName(),
+                                          findDescription(null),
+                                          attributes,
+                                          null,
+                                          operations,
+                                          notifications);            
+        }
+            
+        return _beanInfo;
+    }
+  
+    /* ------------------------------------------------------------ */
+    public Object getAttribute(String name)
+        throws AttributeNotFoundException,
+               MBeanException,
+               ReflectionException
+    {
+        if(log.isDebugEnabled())log.debug("getAttribute "+name);
+        Method getter = (Method)_getter.get(name);
+        if (getter==null)
+            throw new AttributeNotFoundException(name);
+        try
+        {
+            Object o=_object;
+            if (getter.getDeclaringClass().isInstance(this))
+                o=this;
+            return getter.invoke(o,(java.lang.Object[])null);
+        }
+        catch(IllegalAccessException e)
+        {
+            throw new AttributeNotFoundException(e.toString());
+        }
+        catch(InvocationTargetException e)
+        {
+            throw new ReflectionException((Exception)e.getTargetException());
+        }
+    }
+    
+    /* ------------------------------------------------------------ */
+    public AttributeList getAttributes(String[] names)
+    {
+        if(log.isDebugEnabled())log.debug("getAttributes");
+        AttributeList results=new AttributeList(names.length);
+        for (int i=0;i<names.length;i++)
+        {
+            try
+            {
+                results.add(new Attribute(names[i],
+                                          getAttribute(names[i])));
+            }
+            catch(Exception e)
+            {
+                log.warn("Exception",e);
+            }
+        }
+        return results;
+    }
+    
+    
+    /* ------------------------------------------------------------ */
+    public void setAttribute(Attribute attr)
+        throws AttributeNotFoundException,
+               InvalidAttributeValueException,
+               MBeanException,
+               ReflectionException
+    {
+        if (attr==null)
+            return;
+
+        if(log.isDebugEnabled())log.debug("setAttribute "+attr.getName()+"="+attr.getValue());
+        Method setter = (Method)_setter.get(attr.getName());
+        if (setter==null)
+            throw new AttributeNotFoundException(attr.getName());
+        try
+        {
+            Object o=_object;
+            if (setter.getDeclaringClass().isInstance(this))
+                o=this;
+            setter.invoke(o,new Object[]{attr.getValue()});
+        }
+        catch(IllegalAccessException e)
+        {
+            throw new AttributeNotFoundException(e.toString());
+        }
+        catch(InvocationTargetException e)
+        {
+            throw new ReflectionException((Exception)e.getTargetException());
+        }
+    }
+    
+    /* ------------------------------------------------------------ */
+    public AttributeList setAttributes(AttributeList attrs)
+    {
+        log.debug("setAttributes");
+
+        AttributeList results=new AttributeList(attrs.size());
+        Iterator iter = attrs.iterator();
+        while(iter.hasNext())
+        {
+            try
+            {
+                Attribute attr=(Attribute)iter.next();
+                setAttribute(attr);
+                results.add(new Attribute(attr.getName(),
+                                          getAttribute(attr.getName())));
+            }
+            catch(Exception e)
+            {
+                log.warn("Exception",e);
+            }
+        }
+        return results;
+    }
+
+    /* ------------------------------------------------------------ */
+    public Object invoke(String name, Object[] params, String[] signature)
+        throws MBeanException,
+               ReflectionException
+    {
+        if(log.isDebugEnabled())log.debug("invoke "+name);
+
+        String methodKey=name+"(";
+        if (signature!=null)
+            for (int i=0;i<signature.length;i++)
+                methodKey+=(i>0?",":"")+signature[i];
+        methodKey+=")";
+
+        try
+        {
+            Method method = (Method)_method.get(methodKey);
+            if (method==null)
+                throw new NoSuchMethodException(methodKey);
+
+            Object o=_object;
+            if (method.getDeclaringClass().isInstance(this))
+                o=this;
+            return method.invoke(o,params);
+        }
+        catch(NoSuchMethodException e)
+        {
+            throw new ReflectionException(e);
+        }
+        catch(IllegalAccessException e)
+        {
+            throw new MBeanException(e);
+        }
+        catch(InvocationTargetException e)
+        {
+            throw new ReflectionException((Exception)e.getTargetException());
+        }
+        
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void load()
+        throws MBeanException,
+               RuntimeOperationsException,
+               InstanceNotFoundException
+    {
+        log.debug("load");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void store()
+        throws MBeanException,
+               RuntimeOperationsException,
+               InstanceNotFoundException
+    {
+        log.debug("store");
+    }
+
+    /* ------------------------------------------------------------ */
+    public void addNotificationListener(NotificationListener listener,
+                                        NotificationFilter filter,
+                                        Object handback)
+        throws IllegalArgumentException
+    {
+        log.debug("addNotificationListener");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public MBeanNotificationInfo[] getNotificationInfo()
+    {
+        log.debug("getNotificationInfo");
+        return null;
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void removeNotificationListener(NotificationListener listener)
+        throws ListenerNotFoundException
+    {
+        log.debug("removeNotificationListener");
+    }
+
+    /* ------------------------------------------------------------ */
+    public void addAttributeChangeNotificationListener(NotificationListener listener,
+                                               String name,
+                                               Object handback)
+        throws MBeanException,
+               RuntimeOperationsException,
+               IllegalArgumentException
+    {
+        log.debug("addAttributeChangeNotificationListener");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void removeAttributeChangeNotificationListener(NotificationListener listener,
+                                                          String name)
+        throws MBeanException,
+               RuntimeOperationsException,
+               ListenerNotFoundException
+    {
+        log.debug("removeAttributeChangeNotificationListener");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void sendAttributeChangeNotification(Attribute oldAttr,
+                                                Attribute newAttr)
+        throws MBeanException,
+               RuntimeOperationsException
+    {
+        log.debug("sendAttributeChangeNotification");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void sendAttributeChangeNotification(AttributeChangeNotification notify)
+        throws MBeanException,
+               RuntimeOperationsException
+    {
+        log.debug("sendAttributeChangeNotification");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void sendNotification(String notify)
+        throws MBeanException,
+               RuntimeOperationsException
+    {
+        log.debug("sendNotification");
+    }
+    
+    /* ------------------------------------------------------------ */
+    public void sendNotification(Notification notify)
+        throws MBeanException,
+               RuntimeOperationsException
+    {
+        log.debug("sendNotification");
+    }
+
+    /* ------------------------------------------------------------ */
+    /* Find MBean descriptions.
+     * MBean descriptions are searched for in ResourceBundles. Bundles
+     * are looked for in a mbean.property files within each package of
+     * the MBean class inheritance hierachy.
+     * Once a bundle is found, the key is added to object names in the
+     * following order: fully qualied managed resource class name, tail
+     * managed resource class name, tail mbean class name. The string
+     * "MBean" is stripped from the tail of any name.
+     * <P>For example, if the class a.b.C is managed by a MBean
+     * p.q.RMBean which is derived from p.SMBean, then the seach order
+     * for a key x is as follows:<PRE>
+     *   bundle: p.q.mbean    name: a.b.C.x
+     *   bundle: p.q.mbean    name: C.x
+     *   bundle: p.q.mbean    name: R.x
+     *   bundle: p.mbean      name: a.b.C.x
+     *   bundle: p.mbean      name: C.x
+     *   bundle: p.mbean      name: S.x
+     * </PRE>
+     * <P>The convention used for keys passed to this method are:<PRE>
+     *   null or empty         - Object description
+     *   xxx                   - Attribute xxx description
+     *   xxx()                 - Simple operation xxx description
+     *   xxx(type,..)          - Operation xxx with signature desciption
+     *   xxx(type,..)[n]       - Param n of operation xxx description
+     * </PRE>
+     * @param key 
+     * @return Description string.
+     */
+    private String findDescription(String key)
+    {
+        Class lookIn = this.getClass();
+
+        // Array of possible objectNames
+        String[] objectNames=new String[3];
+        objectNames[0]=_object.getClass().getName();
+        if (objectNames[0].indexOf(".")>=0)
+            objectNames[1]=objectNames[0].substring(objectNames[0].lastIndexOf(".")+1);
+
+        while(lookIn!=null)
+        {
+            String pkg=lookIn.getName();
+            int lastDot= pkg.lastIndexOf(".");
+            if (lastDot>0)
+            {
+                objectNames[2]=pkg.substring(lastDot+1);
+                pkg=pkg.substring(0,lastDot);
+            }
+            else
+            {
+                objectNames[2]=pkg;
+                pkg=null;
+            }
+
+            String resource=(pkg==null?"mbean":(pkg.replace('.','/')+"/mbean"));
+            if(log.isTraceEnabled())log.trace("Look for: "+resource);
+
+            try
+            {
+                ResourceBundle bundle=
+                    ResourceBundle.getBundle(resource,
+                                             Locale.getDefault(),
+                                             _object.getClass().getClassLoader());
+            
+                if(log.isTraceEnabled())log.trace("Bundle "+resource);
+                
+                for (int i=0;i<objectNames.length;i++)
+                {
+                    String name=objectNames[i];
+                    
+                    if (name==null)
+                        continue;
+                    if (name.endsWith("MBean"))
+                        name=name.substring(0,name.length()-5);
+                    if (key!=null && key.length()>0)
+                        name+="."+key;
+
+                    try{
+                        String description=bundle.getString(name);
+                        if (description!=null && description.length()>0)
+                            return description;
+                    }
+                    catch(Exception e) { if(log.isTraceEnabled())log.trace(e.toString()); }
+                }
+            }
+            catch(Exception e) { if(log.isTraceEnabled())log.trace(e.toString()); }
+
+            lookIn=lookIn.getSuperclass();
+        }
+
+        if (key==null || key.length()==0)
+            return objectNames[0];
+        
+        return key;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Create a new ObjectName.
+     * Return a new object name. The default implementation is the
+     * results of uniqueObjectName(baseObjectName), if baseObjectName
+     * is not set, then the results of uniqueObjectName(defaultDomain+":");
+     * @return The Object name
+     */
+    protected ObjectName newObjectName(MBeanServer server)
+    {
+        // Create own ObjectName of the form:
+        // package:class=id
+        if (_baseObjectName!=null)
+        {
+            if (_baseObjectName.indexOf(':')>=0)
+                return uniqueObjectName(server,_baseObjectName);
+            return uniqueObjectName(server,getDefaultDomain()+":"+
+                                    _baseObjectName);
+        }
+        return uniqueObjectName(server,getDefaultDomain()+":");
+    }
+
+    /* ------------------------------------------------------------ */
+    public void setBaseObjectName(String s)
+    {
+        _baseObjectName=s;
+    }
+    
+    /* ------------------------------------------------------------ */
+    public String getBaseObjectName()
+    {
+        return _baseObjectName;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Pre registration notification.
+     * If this method is specialized by a derived class that may set
+     * the objectName, then it should call this implementation with
+     * the new objectName.
+     * @param server 
+     * @param oName 
+     * @return The ObjectName to use.
+     */
+    public synchronized ObjectName preRegister(MBeanServer server, ObjectName oName)
+    {
+        _mBeanServer=server;
+        _objectName=oName;
+        if (_objectName==null)
+        {
+            try{oName=newObjectName(server);}
+            catch(Exception e){log.warn("Exception",e);}
+        }
+        if(log.isDebugEnabled())log.debug("preRegister "+_objectName+" -> "+oName);
+        _objectName=oName;
+
+        return _objectName;
+    }
+    
+
+    /* ------------------------------------------------------------ */
+    public void postRegister(Boolean ok)
+    {
+        if (ok.booleanValue())
+            log.info("Registered "+_objectName);
+        else
+        {
+            _mBeanServer=null;
+            _objectName=null;
+        }
+    }
+
+    /* ------------------------------------------------------------ */
+    public void preDeregister()
+    {
+        log.info("Deregister "+_objectName);
+        getComponentMBeans(null,_components);
+        _components.clear();
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Post Deregister.
+     * This implementation destroys this MBean and it cannot be used again.
+     */
+    public void postDeregister()
+    {
+        _beanInfo=null;
+        _mBeanServer=null;
+        _object=null;
+        _objectName=null;
+        if (_getter!=null)
+            _getter.clear();
+        _getter=null;
+        if (_setter!=null)
+            _setter.clear();
+        _setter=null;
+        if (_method!=null)
+            _method.clear();
+        _method=null;
+        if (_attributes!=null)
+            _attributes.clear();
+        _attributes=null;
+        if (_operations!=null)
+            _operations.clear();
+        _operations=null;
+        if (_notifications!=null)
+            _notifications.clear();
+        _notifications=null;
+    }
+
+    /* ------------------------------------------------------------ */
+    /** Add an id clause to a JMX object name.
+     * Used to make unique objectnames when there are no other
+     * distinguishing attributes.
+     * If the passed object name ends with '=', just a unique ID is
+     * added.  Otherwise and classname= clause is added.
+     * @param objectName 
+     * @return objectName with id= class.
+     */
+    public synchronized ObjectName uniqueObjectName(MBeanServer server,
+                                                    String objectName)
+    {
+        return uniqueObjectName(server,_object,objectName);
+    }
+    
+    /* ------------------------------------------------------------ */
+    public synchronized ObjectName uniqueObjectName(MBeanServer server,
+                                                    Object object,
+                                                    String objectName)
+    {
+        if (!objectName.endsWith("="))
+        {
+            String className = object.getClass().getName();
+            if (className.indexOf(".")>0)
+                className=className.substring(className.lastIndexOf(".")+1);
+            if (className.endsWith("MBean"))
+                className=className.substring(0,className.length()-5);
+            if (!objectName.endsWith(":"))
+                objectName+=",";
+            objectName+=className+"=";
+        }
+
+        ObjectName oName=null;
+        try
+        {
+            while(true)
+            {
+                Integer id=(Integer)__objectId.get(objectName);
+                if (id==null)
+                    id=new Integer(0);
+                oName=new ObjectName(objectName+id);
+                id=new Integer(id.intValue()+1);
+                __objectId.put(objectName,id);
+                
+                // If no server, this must be unique
+                if (server==null)
+                    break;
+                
+                // Otherwise let's check it is unique
+                // if not found then it is unique
+                if (!server.isRegistered(oName))
+                    break;
+            }
+        }
+        catch(Exception e)
+        {
+            log.warn("Exception",e);
+        }
+
+        return oName;
+    }
+
+
+    /* ------------------------------------------------------------ */
+    /** Get Component MBeans.
+     * Creates, registers and deregisters MBeans for an array of components.
+     * On each call the passed map is used to determine components that have
+     * already been registers and those that need to be deregistered.
+     * @param components the components.
+     * @param map A map of previously registered components to object
+     * name. If null is passed, a default map for the mbean is used.
+     * @return An array of ObjectNames for each component. 
+     */
+    protected ObjectName[] getComponentMBeans(Object[] components, Map map)
+    {
+        if (map==null)
+            map=_components;
+        ObjectName[] beans=null;   
+        if (components==null)
+            beans = new ObjectName[0];
+        else
+        {
+            beans = new ObjectName[components==null?0:components.length];
+
+            // Add new beans
+            for (int i=0;i<components.length;i++)
+            {
+                ObjectName on = (ObjectName)map.get(components[i]);
+                if (on==null)
+                {
+                    ModelMBean mbean = mbeanFor(components[i]);
+                    if (mbean==null)
+                        log.warn("No mbean for "+components[i]);
+                    else
+                    {
+                        try
+                        {
+                            if (mbean instanceof ModelMBeanImpl)
+                            {
+                                ((ModelMBeanImpl)mbean).setBaseObjectName(getObjectName().toString());
+                                on=getMBeanServer().registerMBean(mbean,null).getObjectName();
+                            }
+                            else
+                            {
+                                on=uniqueObjectName(getMBeanServer(),
+                                                    components[i],
+                                                    getObjectName().toString());
+                                on=getMBeanServer().registerMBean(mbean,on).getObjectName();
+                            }
+                            map.put(components[i],on);
+                        }
+                        catch (Exception e)
+                        {
+                            log.warn("Exception",e);
+                        }
+                    }
+                }
+                beans[i]=on;
+            }
+        }
+        
+        // Delete old beans
+        if (components==null || map.size()>components.length)
+        {
+            Object[] to_delete=new Object[map.size()-beans.length];
+            int d=0;
+            Iterator iter = map.keySet().iterator();
+            keys:
+            while(iter.hasNext())
+            {
+                Object bean = iter.next();
+                if (components!=null)
+                {
+                    for(int i=0;i<components.length;i++)
+                        if (components[i]==bean)
+                            continue keys;
+                }
+                to_delete[d++]=bean;
+            }
+
+            for (;d-->0;)
+            {
+                try{getMBeanServer().unregisterMBean((ObjectName)map.remove(to_delete[d]));}
+                catch (Exception e) {log.warn("Exception",e);}
+            }
+        }
+        
+        return beans;
+    }
+    
+    /** Unregister mbeans for already registered components
+     * @param map
+     */
+    protected void destroyComponentMBeans (Map map)
+    {
+        //if no map of registered mbean names is passed,
+        //use the default map
+        if (null==map)
+            map = _components;
+        
+        if (map==null)
+            return;
+        
+        Iterator itor = map.values().iterator();
+        while (itor.hasNext())
+        {
+            try
+            {
+                ObjectName o = (ObjectName)itor.next();
+                getMBeanServer().unregisterMBean(o);
+                itor.remove();
+            }
+            catch (Exception e) {log.warn("Exception",e);}
+        }
+            
+    }
+}

Added: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/TypeUtil.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/TypeUtil.java?rev=367400&view=auto
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/TypeUtil.java (added)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/util/jmx/TypeUtil.java Mon Jan  9 13:29:16 2006
@@ -0,0 +1,430 @@
+// ========================================================================
+// $Id: TypeUtil.java,v 1.14 2005/12/06 00:51:40 gregwilkins Exp $
+// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at 
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================================================================
+
+// This class was originally developed by the Jetty project
+
+package org.apache.cocoon.util.jmx;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/* ------------------------------------------------------------ */
+/** TYPE Utilities.
+ * Provides various static utiltiy methods for manipulating types and their
+ * string representations.
+ *
+ * @since Jetty 4.1
+ * @version $Revision: 1.14 $
+ * @author Greg Wilkins (gregw)
+ */
+public class TypeUtil
+{
+    private static Log log = LogFactory.getLog(TypeUtil.class);
+
+    /* ------------------------------------------------------------ */
+    private static final HashMap name2Class=new HashMap();
+    static
+    {
+        name2Class.put("boolean",java.lang.Boolean.TYPE);
+        name2Class.put("byte",java.lang.Byte.TYPE);
+        name2Class.put("char",java.lang.Character.TYPE);
+        name2Class.put("double",java.lang.Double.TYPE);
+        name2Class.put("float",java.lang.Float.TYPE);
+        name2Class.put("int",java.lang.Integer.TYPE);
+        name2Class.put("long",java.lang.Long.TYPE);
+        name2Class.put("short",java.lang.Short.TYPE);
+        name2Class.put("void",java.lang.Void.TYPE);
+        
+        name2Class.put("java.lang.Boolean.TYPE",java.lang.Boolean.TYPE);
+        name2Class.put("java.lang.Byte.TYPE",java.lang.Byte.TYPE);
+        name2Class.put("java.lang.Character.TYPE",java.lang.Character.TYPE);
+        name2Class.put("java.lang.Double.TYPE",java.lang.Double.TYPE);
+        name2Class.put("java.lang.Float.TYPE",java.lang.Float.TYPE);
+        name2Class.put("java.lang.Integer.TYPE",java.lang.Integer.TYPE);
+        name2Class.put("java.lang.Long.TYPE",java.lang.Long.TYPE);
+        name2Class.put("java.lang.Short.TYPE",java.lang.Short.TYPE);
+        name2Class.put("java.lang.Void.TYPE",java.lang.Void.TYPE);
+
+        name2Class.put("java.lang.Boolean",java.lang.Boolean.class);
+        name2Class.put("java.lang.Byte",java.lang.Byte.class);
+        name2Class.put("java.lang.Character",java.lang.Character.class);
+        name2Class.put("java.lang.Double",java.lang.Double.class);
+        name2Class.put("java.lang.Float",java.lang.Float.class);
+        name2Class.put("java.lang.Integer",java.lang.Integer.class);
+        name2Class.put("java.lang.Long",java.lang.Long.class);
+        name2Class.put("java.lang.Short",java.lang.Short.class);
+
+        name2Class.put("Boolean",java.lang.Boolean.class);
+        name2Class.put("Byte",java.lang.Byte.class);
+        name2Class.put("Character",java.lang.Character.class);
+        name2Class.put("Double",java.lang.Double.class);
+        name2Class.put("Float",java.lang.Float.class);
+        name2Class.put("Integer",java.lang.Integer.class);
+        name2Class.put("Long",java.lang.Long.class);
+        name2Class.put("Short",java.lang.Short.class);
+
+        name2Class.put(null,java.lang.Void.TYPE);
+        name2Class.put("string",java.lang.String.class);
+        name2Class.put("String",java.lang.String.class);
+        name2Class.put("java.lang.String",java.lang.String.class);
+    }
+    
+    /* ------------------------------------------------------------ */
+    private static final HashMap class2Name=new HashMap();
+    static
+    {
+        class2Name.put(java.lang.Boolean.TYPE,"boolean");
+        class2Name.put(java.lang.Byte.TYPE,"byte");
+        class2Name.put(java.lang.Character.TYPE,"char");
+        class2Name.put(java.lang.Double.TYPE,"double");
+        class2Name.put(java.lang.Float.TYPE,"float");
+        class2Name.put(java.lang.Integer.TYPE,"int");
+        class2Name.put(java.lang.Long.TYPE,"long");
+        class2Name.put(java.lang.Short.TYPE,"short");
+        class2Name.put(java.lang.Void.TYPE,"void");
+
+        class2Name.put(java.lang.Boolean.class,"java.lang.Boolean");
+        class2Name.put(java.lang.Byte.class,"java.lang.Byte");
+        class2Name.put(java.lang.Character.class,"java.lang.Character");
+        class2Name.put(java.lang.Double.class,"java.lang.Double");
+        class2Name.put(java.lang.Float.class,"java.lang.Float");
+        class2Name.put(java.lang.Integer.class,"java.lang.Integer");
+        class2Name.put(java.lang.Long.class,"java.lang.Long");
+        class2Name.put(java.lang.Short.class,"java.lang.Short");
+        
+        class2Name.put(null,"void");
+        name2Class.put(java.lang.String.class,"java.lang.String");
+    }
+    
+    /* ------------------------------------------------------------ */
+    private static final HashMap class2Value=new HashMap();
+    static
+    {
+        try
+        {
+            Class[] s ={java.lang.String.class};
+            
+            class2Value.put(java.lang.Boolean.TYPE,
+                           java.lang.Boolean.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Byte.TYPE,
+                           java.lang.Byte.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Double.TYPE,
+                           java.lang.Double.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Float.TYPE,
+                           java.lang.Float.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Integer.TYPE,
+                           java.lang.Integer.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Long.TYPE,
+                           java.lang.Long.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Short.TYPE,
+                           java.lang.Short.class.getMethod("valueOf",s));
+
+            class2Value.put(java.lang.Boolean.class,
+                           java.lang.Boolean.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Byte.class,
+                           java.lang.Byte.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Double.class,
+                           java.lang.Double.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Float.class,
+                           java.lang.Float.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Integer.class,
+                           java.lang.Integer.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Long.class,
+                           java.lang.Long.class.getMethod("valueOf",s));
+            class2Value.put(java.lang.Short.class,
+                           java.lang.Short.class.getMethod("valueOf",s));
+        }
+        catch(Exception e)
+        {
+            log.warn("Exception",e);
+        }
+    }
+
+    /* ------------------------------------------------------------ */
+    private static Class[] stringArg = { java.lang.String.class };
+    
+    /* ------------------------------------------------------------ */
+    private static int intCacheSize=
+        Integer.getInteger("org.mortbay.util.TypeUtil.IntegerCacheSize",600).intValue();
+    private static Integer[] integerCache = new Integer[intCacheSize];
+    private static String[] integerStrCache = new String[intCacheSize];
+    private static Integer minusOne = new Integer(-1);
+    
+    /* ------------------------------------------------------------ */
+    /** Class from a canonical name for a type.
+     * @param name A class or type name.
+     * @return A class , which may be a primitive TYPE field..
+     */
+    public static Class fromName(String name)
+    {
+        return (Class)name2Class.get(name);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Canonical name for a type.
+     * @param type A class , which may be a primitive TYPE field.
+     * @return Canonical name.
+     */
+    public static String toName(Class type)
+    {
+        return (String)class2Name.get(type);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Convert String value to instance.
+     * @param type The class of the instance, which may be a primitive TYPE field.
+     * @param value The value as a string.
+     * @return The value as an Object.
+     */
+    public static Object valueOf(Class type, String value)
+    {
+        try
+        {
+            if (type.equals(java.lang.String.class))
+                return value;
+            
+            Method m = (Method)class2Value.get(type);
+            if (m!=null)
+                return m.invoke(null,new Object[] {value});
+
+            if (type.equals(java.lang.Character.TYPE) ||
+                type.equals(java.lang.Character.class))
+                return new Character(value.charAt(0));
+
+            Constructor c = type.getConstructor(stringArg);
+            return c.newInstance(new Object[] {value});   
+        }
+        catch(NoSuchMethodException e)
+        {
+            if( log.isDebugEnabled()) log.debug("Ignored",e);
+        }
+        catch(IllegalAccessException e)
+        {
+            if( log.isDebugEnabled()) log.debug("Ignored",e);
+        }
+        catch(InstantiationException e)
+        {
+            if( log.isDebugEnabled()) log.debug("Ignored",e);
+        }
+        catch(InvocationTargetException e)
+        {
+            if (e.getTargetException() instanceof Error)
+                throw (Error)(e.getTargetException());
+            if( log.isDebugEnabled()) log.debug("Ignored",e);
+        }
+        return null;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Convert String value to instance.
+     * @param type classname or type (eg int)
+     * @param value The value as a string.
+     * @return The value as an Object.
+     */
+    public static Object valueOf(String type, String value)
+    {
+        return valueOf(fromName(type),value);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Convert int to Integer using cache. 
+     */
+    public static Integer newInteger(int i)
+    {
+        if (i>=0 && i<intCacheSize)
+        {
+            if (integerCache[i]==null)
+                integerCache[i]=new Integer(i);
+            return integerCache[i];
+        }
+        else if (i==-1)
+            return minusOne;
+        return new Integer(i);
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    /** Convert int to String using cache. 
+     */
+    public static String toString(int i)
+    {
+        if (i>=0 && i<intCacheSize)
+        {
+            if (integerStrCache[i]==null)
+                integerStrCache[i]=Integer.toString(i);
+            return integerStrCache[i];
+        }
+        else if (i==-1)
+            return "-1";
+        return Integer.toString(i);
+    }
+
+
+    /* ------------------------------------------------------------ */
+    /** Parse an int from a substring.
+     * Negative numbers are not handled.
+     * @param s String
+     * @param offset Offset within string
+     * @param length Length of integer or -1 for remainder of string
+     * @param base base of the integer
+     * @exception NumberFormatException 
+     */
+    public static int parseInt(String s, int offset, int length, int base)
+        throws NumberFormatException
+    {
+        int value=0;
+
+        if (length<0)
+            length=s.length()-offset;
+
+        for (int i=0;i<length;i++)
+        {
+            char c=s.charAt(offset+i);
+            
+            int digit=c-'0';
+            if (digit<0 || digit>=base || digit>=10)
+            {
+                digit=10+c-'A';
+                if (digit<10 || digit>=base)
+                    digit=10+c-'a';
+            }
+            if (digit<0 || digit>=base)
+                throw new NumberFormatException(s.substring(offset,offset+length));
+            value=value*base+digit;
+        }
+        return value;
+    }
+
+    /* ------------------------------------------------------------ */
+    public static byte[] parseBytes(String s, int base)
+    {
+        byte[] bytes=new byte[s.length()/2];
+        for (int i=0;i<s.length();i+=2)
+            bytes[i/2]=(byte)TypeUtil.parseInt(s,i,2,base);
+        return bytes;
+    }
+
+    /* ------------------------------------------------------------ */
+    public static String toString(byte[] bytes, int base)
+    {
+        StringBuffer buf = new StringBuffer();
+        for (int i=0;i<bytes.length;i++)
+        {
+            int bi=0xff&bytes[i];
+            int c='0'+(bi/base)%base;
+            if (c>'9')
+                c= 'a'+(c-'0'-10);
+            buf.append((char)c);
+            c='0'+bi%base;
+            if (c>'9')
+                c= 'a'+(c-'0'-10);
+            buf.append((char)c);
+        }
+        return buf.toString();
+    }
+
+    /* ------------------------------------------------------------ */
+    /** 
+     * @param b An ASCII encoded character 0-9 a-f A-F
+     * @return The byte value of the character 0-16.
+     */
+    public static byte convertHexDigit( byte b )
+    {
+        if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
+        if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
+        if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
+        return 0;
+    }
+
+    /* ------------------------------------------------------------ */
+    public static char toHexChar(int b)
+    {   
+        return (char)(b<10?('0'+b):('A'+b-10));
+    }
+    
+    /* ------------------------------------------------------------ */
+    public static String toHexString(byte[] b)
+    {   
+        StringBuffer buf = new StringBuffer();
+        for (int i=0;i<b.length;i++)
+        {
+            int bi=0xff&b[i];
+            int c='0'+(bi/16)%16;
+            if (c>'9')
+                c= 'A'+(c-'0'-10);
+            buf.append((char)c);
+            c='0'+bi%16;
+            if (c>'9')
+                c= 'a'+(c-'0'-10);
+            buf.append((char)c);
+        }
+        return buf.toString();
+    }
+    
+    /* ------------------------------------------------------------ */
+    public static String toHexString(byte[] b,int offset,int length)
+    {   
+        StringBuffer buf = new StringBuffer();
+        for (int i=offset;i<offset+length;i++)
+        {
+            int bi=0xff&b[i];
+            int c='0'+(bi/16)%16;
+            if (c>'9')
+                c= 'A'+(c-'0'-10);
+            buf.append((char)c);
+            c='0'+bi%16;
+            if (c>'9')
+                c= 'a'+(c-'0'-10);
+            buf.append((char)c);
+        }
+        return buf.toString();
+    }
+    
+    /* ------------------------------------------------------------ */
+    public static byte[] fromHexString(String s)
+    {   
+        if (s.length()%2!=0)
+            throw new IllegalArgumentException(s);
+        byte[] array = new byte[s.length()/2];
+        for (int i=0;i<array.length;i++)
+        {
+            int b = Integer.parseInt(s.substring(i*2,i*2+2),16);
+            array[i]=(byte)(0xff&b);
+        }    
+        return array;
+    }
+    
+
+    public static void dump(Class c)
+    {
+        System.err.println("Dump: "+c);
+        dump(c.getClassLoader());
+    }
+
+    public static void dump(ClassLoader cl)
+    {
+        System.err.println("Dump Loaders:");
+        while(cl!=null)
+        {
+            System.err.println("  loader "+cl);
+            cl = cl.getParent();
+        }
+    }
+}



Mime
View raw message