costin 2002/11/01 16:35:14
Modified: modeler/src/java/org/apache/commons/modeler Registry.java
Log:
Few changes - preserving backward compat ( I only added new stuff and
made minor changes to the old ones ).
- merged the code from the DynamicMbean from tomcat util. I kept
all the code doing introspection - but now it creates a model mbean
- added code to 'discover' mbean descriptors in META-INF - that
will solve one of the problems with support of 3rd party modules.
- other cosmetic changes to make it work with the BaseRegistry.
Revision Changes Path
1.5 +272 -24
jakarta-commons/modeler/src/java/org/apache/commons/modeler/Registry.java
Index: Registry.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/modeler/src/java/org/apache/commons/modeler/Registry.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Registry.java 11 Oct 2002 22:18:07 -0000 1.4
+++ Registry.java 2 Nov 2002 00:35:14 -0000 1.5
@@ -1,8 +1,4 @@
/*
- * $Header$
- * $Revision$
- * $Date$
- *
* ====================================================================
*
* The Apache Software License, Version 1.1
@@ -65,14 +61,14 @@
package org.apache.commons.modeler;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
+import java.io.*;
+import java.net.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import javax.management.*;
+import javax.management.modelmbean.ModelMBean;
+
import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -88,20 +84,21 @@
* synchronized.</p>
*
* @author Craig R. McClanahan
+ * @author Costin Manolache
* @version $Revision$ $Date$
*/
-
-public final class Registry {
+public final class Registry extends BaseRegistry {
// ----------------------------------------------------------- Constructors
/**
- * Private constructor to require use of the factory create method.
+ * Constructor to require use of the factory create method.
+ * It is called from BaseRegistry
*/
- private Registry() {
-
+ protected Registry() {
+
super();
}
@@ -216,8 +213,8 @@
private static MBeanServer server = null;
- // --------------------------------------------------------- Static Methods
+ // --------------------------------------------------------- Static Methods
/**
* Factory method to create (if necessary) and return our
@@ -233,7 +230,9 @@
}
-
+ // XXX This should be decoupled - Registry should only deal with
+ // type info, and it may be nice to not depend directly on JMX.
+
/**
* Factory method to create (if necessary) and return our
* <code>MBeanServer</code> instance.
@@ -253,7 +252,6 @@
return (server);
}
-
/**
* Load the registry from the XML input found in the specified input
* stream.
@@ -262,13 +260,30 @@
* information
*
* @exception Exception if any parsing or processing error occurs
+ * @deprecated use normal class method instead
*/
- public static void loadRegistry(InputStream stream)
- throws Exception {
+ public static void loadRegistry(InputStream stream) throws Exception {
+ Registry registry = getRegistry();
+ registry.loadDescriptors( stream, "modeler" );
+ }
+
+ /**
+ * Load the registry from the XML input found in the specified input
+ * stream.
+ *
+ * @param stream InputStream containing the registry configuration
+ * information
+ *
+ * @exception Exception if any parsing or processing error occurs
+ */
+ public void loadDescriptors(InputStream stream, String type)
+ throws Exception
+ {
long t1=System.currentTimeMillis();
// Create a digester to use for parsing
- Registry registry = getRegistry();
+ Registry registry = this;
+
Digester digester = new Digester();
digester.setNamespaceAware(false);
digester.setValidating(false);
@@ -379,4 +394,237 @@
}
+
+ // ---------------------- BaseRegistry overrides --------------------------
+ public Object getMBeanServer() {
+ return getServer();
+ }
+
+
+ public void registerComponent(Object bean, String domain, String type,
+ String name)
+ {
+ ManagedBean managed = registry.findManagedBean(type);
+
+ ModelMBean mbean = managed.createMBean(bean);
+
+ getServer().registerMBean( mbean, new ObjectName( domain + ": type="
+ + type + " ; " + name ));
+ }
+
+ public void registerClass(Class beanClass, String domain, String className,
+ String type, Object source)
+ {
+ }
+
+ public void unregisterMBean( String name ) {
+ try {
+ ObjectName oname=new ObjectName( name );
+
+ getServer().unregisterMBean( oname );
+ } catch( Throwable t ) {
+ log.error( "Error unregistering mbean ", t );
+ }
+ }
+
+
+ public String registerMBean( String domain, String name ) {
+ try {
+ // XXX use aliases, suffix only, proxy.getName(), etc
+ String fullName=domain + ": " + name;
+ ObjectName oname=new ObjectName( fullName );
+
+ if( getServer().isRegistered( oname )) {
+ log.info("Unregistering " + oname );
+ getServer().unregisterMBean( oname );
+ }
+ getServer().registerMBean( this, oname );
+ return fullName;
+ } catch( Throwable t ) {
+ log.error( "Error creating mbean ", t );
+ return null;
+ }
+ }
+
+ public static String MODELER_MANIFEST="/META-INF/modeler-mbeans.xml";
+
+ /** Discover all META-INF/modeler.xml files in classpath and register the
components
+ */
+ public void loadDescriptors(ClassLoader cl, String type) {
+ try {
+ Enumeration en=cl.getResources(MODELER_MANIFEST);
+ while( en.hasMoreElements() ) {
+ URL url=(URL)en.nextElement();
+ InputStream is=url.openStream();
+ if( log.isDebugEnabled()) log.debug("Loading " + url);
+ loadDescriptors(is, "modeler" );
+ }
+ } catch( Exception ex ) {
+ ex.printStackTrace();
+ }
+ }
+
+ // ------------ Implementation for non-declared introspection classes
+
+
+ // createMBean == registerClass + registerMBean
+
+ private boolean supportedType( Class ret ) {
+ return ret == String.class ||
+ ret == Integer.class ||
+ ret == Integer.TYPE ||
+ ret == Long.class ||
+ ret == Long.TYPE ||
+ ret == java.io.File.class ||
+ ret == Boolean.class ||
+ ret == Boolean.TYPE
+ ;
+ }
+
+ /** Process the methods and extract 'attributes', methods, etc
+ *
+ */
+ private void initMethods(Class realClass,
+ Method methods[],
+ Hashtable attMap, Hashtable getAttMap,
+ Hashtable setAttMap, Hashtable invokeAttMap)
+ {
+ for (int j = 0; j < methods.length; ++j) {
+ String name=methods[j].getName();
+
+ if( name.startsWith( "get" ) ) {
+ if( methods[j].getParameterTypes().length != 0 ) {
+ continue;
+ }
+ if( ! Modifier.isPublic( methods[j].getModifiers() ) ) {
+ //log.debug("not public " + methods[j] );
+ continue;
+ }
+ Class ret=methods[j].getReturnType();
+ if( ! supportedType( ret ) ) {
+ if( log.isDebugEnabled() )
+ log.debug("Unsupported " + ret );
+ continue;
+ }
+ name=unCapitalize( name.substring(3));
+
+ getAttMap.put( name, methods[j] );
+ // just a marker, we don't use the value
+ attMap.put( name, methods[j] );
+ } else if( name.startsWith( "is" ) ) {
+ // not used in our code. Add later
+
+ } else if( name.startsWith( "set" ) ) {
+ Class params[]=methods[j].getParameterTypes();
+ if( params.length != 1 ) {
+ continue;
+ }
+ if( ! Modifier.isPublic( methods[j].getModifiers() ) )
+ continue;
+ Class ret=params[0];
+ if( ! supportedType( ret ) ) {
+ continue;
+ }
+ name=unCapitalize( name.substring(3));
+ setAttMap.put( name, methods[j] );
+ attMap.put( name, methods[j] );
+ } else {
+ if( methods[j].getParameterTypes().length != 0 ) {
+ continue;
+ }
+ if( methods[j].getDeclaringClass() == Object.class )
+ continue;
+ if( ! Modifier.isPublic( methods[j].getModifiers() ) )
+ continue;
+ invokeAttMap.put( name, methods[j]);
+ }
+ }
+ }
+
+ /**
+ * @todo Find if the 'className' is the name of the MBean or
+ * the real class ( I suppose first )
+ * @todo Read (optional) descriptions from a .properties, generated
+ * from source
+ * @todo Deal with constructors
+ *
+ */
+ private ManagedBean createManagedBean(String domain, Object real, String type) {
+ ManagedBean mbean= new ManagedBean();
+
+ Method methods[]=null;
+
+ Hashtable attMap=new Hashtable();
+ // key: attribute val: getter method
+ Hashtable getAttMap=new Hashtable();
+ // key: attribute val: setter method
+ Hashtable setAttMap=new Hashtable();
+ // key: operation val: invoke method
+ Hashtable invokeAttMap=new Hashtable();
+
+ Class realClass=real.getClass();
+ methods = realClass.getMethods();
+
+ initMethods(realClass, methods, attMap, getAttMap, setAttMap, invokeAttMap
);
+
+ if( type==null) type=Modeler.getModeler().generateSeqName(domain,
realClass);
+
+ try {
+
+ Enumeration en=attMap.keys();
+ while( en.hasMoreElements() ) {
+ String name=(String)en.nextElement();
+ AttributeInfo ai=new AttributeInfo();
+ ai.setName( name );
+ ai.setGetMethod( ((Method)getAttMap.get(name)).getName());
+ ai.setSetMethod( ((Method)setAttMap.get(name)).getName());
+ ai.setDescription("Introspected attribute " + name );
+
+ mbean.addAttribute(ai);
+ }
+
+ en=invokeAttMap.keys();
+ while( en.hasMoreElements() ) {
+ String name=(String)en.nextElement();
+ Method m=(Method)invokeAttMap.get(name);
+ if( m!=null && name != null ) {
+ OperationInfo op=new OperationInfo();
+ op.setName(name);
+ op.setReturnType(m.getReturnType().getName());
+ Class parms[]=m.getParameterTypes();
+ for(int i=0; i<parms.length; i++ ) {
+ ParameterInfo pi=new ParameterInfo();
+ pi.setType(parms[i].getName());
+ op.addParameter(pi);
+ }
+ mbean.addOperation(op);
+ } else {
+ log.error("Null arg " + name + " " + m );
+ }
+ }
+
+ if( log.isDebugEnabled())
+ log.debug("Setting name: " + type );
+ mbean.setName( type );
+
+ return mbean;
+ } catch( Exception ex ) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+
+ // -------------------- Utils --------------------
+
+ private static String unCapitalize(String name) {
+ if (name == null || name.length() == 0) {
+ return name;
+ }
+ char chars[] = name.toCharArray();
+ chars[0] = Character.toLowerCase(chars[0]);
+ return new String(chars);
+ }
+
}
+
\ No newline at end of file
--
To unsubscribe, e-mail: <mailto:commons-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@;jakarta.apache.org>