You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2007/11/24 12:17:01 UTC

svn commit: r597836 - /mina/trunk/integration-jmx/src/main/java/org/apache/mina/integration/jmx/DefaultModelMBean.java

Author: trustin
Date: Sat Nov 24 03:17:00 2007
New Revision: 597836

URL: http://svn.apache.org/viewvc?rev=597836&view=rev
Log:
simplified DefaultModelMBean

Modified:
    mina/trunk/integration-jmx/src/main/java/org/apache/mina/integration/jmx/DefaultModelMBean.java

Modified: mina/trunk/integration-jmx/src/main/java/org/apache/mina/integration/jmx/DefaultModelMBean.java
URL: http://svn.apache.org/viewvc/mina/trunk/integration-jmx/src/main/java/org/apache/mina/integration/jmx/DefaultModelMBean.java?rev=597836&r1=597835&r2=597836&view=diff
==============================================================================
--- mina/trunk/integration-jmx/src/main/java/org/apache/mina/integration/jmx/DefaultModelMBean.java (original)
+++ mina/trunk/integration-jmx/src/main/java/org/apache/mina/integration/jmx/DefaultModelMBean.java Sat Nov 24 03:17:00 2007
@@ -18,7 +18,6 @@
 
 import java.beans.PropertyDescriptor;
 import java.beans.PropertyEditor;
-import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.SocketAddress;
@@ -42,9 +41,12 @@
 import javax.management.MBeanInfo;
 import javax.management.MBeanNotificationInfo;
 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;
@@ -58,21 +60,20 @@
 
 import org.apache.commons.beanutils.MethodUtils;
 import org.apache.commons.beanutils.PropertyUtils;
-import org.apache.mina.common.AttributeKey;
 import org.apache.mina.common.DefaultIoFilterChainBuilder;
 import org.apache.mina.common.IoFilter;
 import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoFilterChainBuilder;
+import org.apache.mina.common.IoFuture;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoService;
 import org.apache.mina.common.IoSession;
 import org.apache.mina.common.IoSessionDataStructureFactory;
-import org.apache.mina.common.TrafficMask;
 import org.apache.mina.common.TransportMetadata;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class DefaultModelMBean implements ModelMBean {
+class DefaultModelMBean implements ModelMBean, MBeanRegistration {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
     private final Object source;
@@ -80,6 +81,9 @@
     private final MBeanInfo info;
     private final Map<String, PropertyDescriptor> propertyDescriptors =
         new HashMap<String, PropertyDescriptor>();
+    
+    private volatile MBeanServer server;
+    private volatile ObjectName name;
 
     public DefaultModelMBean(Object source) {
         if (source == null) {
@@ -101,8 +105,20 @@
     
     public Object getAttribute(String name) throws AttributeNotFoundException,
             MBeanException, ReflectionException {
+        
+        // Handle synthetic attributes first.
+        if (source instanceof IoSession && name.equals("attributes")) {
+            Map<Object, Object> result = new HashMap<Object, Object>();
+            IoSession session = (IoSession) source;
+            for (Object key: session.getAttributeKeys()) {
+                result.put(key, session.getAttribute(key));
+            }
+            return convertAttributeValue("attributes", result);
+        }
+        
+        // And then try reflection.
         try {
-            return convertReturnValue(
+            return convertAttributeValue(
                     name, PropertyUtils.getNestedProperty(source, name));
         } catch (IllegalAccessException e) {
             throw new ReflectionException(e);
@@ -136,12 +152,24 @@
 
     public Object invoke(String name, Object params[], String signature[])
             throws MBeanException, ReflectionException {
+
+        // Handle synthetic operations first.
+        if (name.equals("unregisterMBean")) {
+            try {
+                server.unregisterMBean(this.name);
+                return null;
+            } catch (InstanceNotFoundException e) {
+                throw new MBeanException(e);
+            }
+        }
+        
+        // And then try reflection.
         try {
             Class<?>[] paramTypes = new Class[signature.length];
             for (int i = 0; i < paramTypes.length; i ++) {
                 paramTypes[i] = getAttributeClass(signature[i]);
             }
-            return convertReturnValue(
+            return convertAttributeValue(
                     "", MethodUtils.invokeMethod(source, name, params, paramTypes));
         } catch (ClassNotFoundException e) {
             throw new ReflectionException(e);
@@ -302,11 +330,29 @@
         throw new RuntimeOperationsException(new UnsupportedOperationException());
     }
 
+    public ObjectName preRegister(MBeanServer server, ObjectName name)
+            throws Exception {
+        this.server = server;
+        this.name = name;
+        return name;
+    }
+
+    public void postRegister(Boolean registrationDone) {
+    }
+
+    public void preDeregister() throws Exception {
+    }
+
+    public void postDeregister() {
+        this.server = null;
+        this.name = null;
+    }
+
     @Override
     public String toString() {
         return source.toString();
     }
-    
+
     private MBeanInfo createModelMBeanInfo(Object source) {
         String className = source.getClass().getName();
         String description = "";
@@ -349,6 +395,9 @@
             if (IoSession.class.isAssignableFrom(type) && pname.equals("attachment")) {
                 continue;
             }
+            if (IoSession.class.isAssignableFrom(type) && pname.equals("attributeKeys")) {
+                continue;
+            }
             if (IoSession.class.isAssignableFrom(type) && pname.equals("closeFuture")) {
                 continue;
             }
@@ -372,13 +421,19 @@
             String fqpn = prefix + pname;
             boolean writable = p.getWriteMethod() != null | isWritable(type, pname);
             attributes.add(new ModelMBeanAttributeInfo(
-                    fqpn, convertReturnType(fqpn, p.getPropertyType()).getName(),
+                    fqpn, convertAttributeType(fqpn, p.getPropertyType()).getName(),
                     p.getShortDescription(),
                     true, writable,
                     p.getReadMethod().getName().startsWith("is")));
             
             propertyDescriptors.put(fqpn, p);
         }
+        
+        if (object instanceof IoSession) {
+            attributes.add(new ModelMBeanAttributeInfo(
+                    "attributes", Map.class.getName(), "attributes",
+                    true, false, false));
+        }
     }
 
     private boolean expandAttribute(
@@ -406,11 +461,14 @@
         return false;
     }
     
-    private void addOperations(List<ModelMBeanOperationInfo> operations, Object object) {
+    private void addOperations(
+            List<ModelMBeanOperationInfo> operations, Object object) {
+
         for (Method m: object.getClass().getMethods()) {
             String mname = m.getName();
             // Ignore getters and setters.
-            if (mname.startsWith("is") || mname.startsWith("get") || mname.startsWith("set")) {
+            if (mname.startsWith("is") || mname.startsWith("get") ||
+                mname.startsWith("set")) {
                 continue;
             }
             
@@ -446,139 +504,134 @@
             for (Class<?> ptype: m.getParameterTypes()) {
                 String pname = "p" + (i ++);
                 signature.add(new MBeanParameterInfo(
-                        pname, convertReturnType("", ptype).getName(), pname));
+                        pname, convertAttributeType("", ptype).getName(), pname));
             }
 
             operations.add(new ModelMBeanOperationInfo(
                     m.getName(), m.getName(),
                     signature.toArray(new MBeanParameterInfo[signature.size()]),
-                    convertReturnType("", m.getReturnType()).getName(),
+                    convertOperationReturnType(
+                            m.getName(), m.getReturnType()).getName(),
                     ModelMBeanOperationInfo.ACTION));
         }
+        
+        operations.add(new ModelMBeanOperationInfo(
+                "unregisterMBean", "unregisterMBean",
+                new MBeanParameterInfo[0], void.class.getName(), 
+                ModelMBeanOperationInfo.ACTION));
     }
     
     private boolean isWritable(Class<?> type, String pname) {
-        if (IoService.class.isAssignableFrom(type) && pname.equals("localAddresses")) {
-            return true;
-        }
-        
-        return false;
+        return IoService.class.isAssignableFrom(type) && 
+               pname.equals("localAddresses");
     }
     
-    private Object convert(Object v, Class<?> type) throws ReflectionException {
+    private Object convert(Object v, Class<?> dstType) throws ReflectionException {
         if (v == null) {
             return null;
         }
         
-        if (type.isAssignableFrom(v.getClass())) {
+        if (dstType.isAssignableFrom(v.getClass())) {
             return v;
         }
         
         if (v instanceof String) {
-            String s = (String) v;
-            if (type == TrafficMask.class) {
-                if ("all".equalsIgnoreCase(s)) {
-                    return TrafficMask.ALL;
-                }
-                if ("read".equalsIgnoreCase(s)) {
-                    return TrafficMask.READ;
-                }
-                if ("write".equalsIgnoreCase(s)) {
-                    return TrafficMask.WRITE;
-                }
-                if ("none".equalsIgnoreCase(s)) {
-                    return TrafficMask.NONE;
-                }
-                throw new IllegalArgumentException(
-                        s + " (expected: all, read, write or none)");
-            }
-
-            PropertyEditor editor = getPropertyEditor(type);
+            PropertyEditor editor = getPropertyEditor(dstType);
             if (editor == null) {
                 throw new ReflectionException(new ClassNotFoundException(
-                        "Failed to find a PropertyEditor for " + type.getSimpleName()));
+                        "Failed to find a PropertyEditor for " +
+                        dstType.getSimpleName()));
             }
-            editor.setAsText(s);
+            editor.setAsText((String) v);
             return editor.getValue();
         }
 
         return v;
     }
 
-    private PropertyEditor getPropertyEditor(Class<?> type) {
-        if (transportMetadata != null && type == SocketAddress.class) {
-            type = transportMetadata.getAddressType();
+    private PropertyEditor getPropertyEditor(Class<?> propType) {
+        if (transportMetadata != null && propType == SocketAddress.class) {
+            propType = transportMetadata.getAddressType();
         }
 
         try {
-            return (PropertyEditor) IoSession.class.getClassLoader().loadClass(
+            return (PropertyEditor) getClass().getClassLoader().loadClass(
                 "org.apache.mina.integration.beans." +
-                type.getSimpleName() + "Editor").newInstance();
+                propType.getSimpleName() + "Editor").newInstance();
         } catch (Exception e) {
             return null;
         }
     }
+    
+    private Class<?> convertOperationReturnType(
+            String opName, Class<?> opReturnType) {
 
-    private Class<?> convertReturnType(String name, Class<?> type) {
-        if (Class.class.isAssignableFrom(type)) {
-            return String.class;
-        }
-        
-        if (SocketAddress.class.isAssignableFrom(type)) {
-            return String.class;
+        if (IoFuture.class.isAssignableFrom(opReturnType)) {
+            return void.class;
         }
-        
-        if ((type == Long.class || type == long.class)) {
-            if (name.endsWith("Time") &&
-                !propertyDescriptors.containsKey(name + "InMillis")) {
+        return convertAttributeType("", opReturnType);
+    }
+
+    private Class<?> convertAttributeType(
+            String attrName, Class<?> attrType) {
+
+        if ((attrType == Long.class || attrType == long.class)) {
+            if (attrName.endsWith("Time") &&
+                !propertyDescriptors.containsKey(attrName + "InMillis")) {
                 return Date.class;
             }
             
-            if (name.equals("id")) {
+            if (attrName.equals("id")) {
                 return String.class;
             }
         }
         
-        if (type == AttributeKey.class) {
-            return String.class;
-        }
-
-        if (type == TrafficMask.class) {
-            return String.class;
-        }
-        
-        if (IoHandler.class.isAssignableFrom(type)) {
-            return String.class;
-        }
-        
-        if (IoSession.class.isAssignableFrom(type)) {
-            return String.class;
-        }
-        
-        if (IoService.class.isAssignableFrom(type)) {
-            return String.class;
-        }
-        
-        if (IoFilterChain.class.isAssignableFrom(type)) {
+        if (IoFilterChain.class.isAssignableFrom(attrType)) {
             return List.class;
         }
         
-        if (IoFilterChainBuilder.class.isAssignableFrom(type)) {
+        if (IoFilterChainBuilder.class.isAssignableFrom(attrType)) {
             return List.class;
         }
         
-        if (IoSessionDataStructureFactory.class.isAssignableFrom(type)) {
-            return String.class;
+        if (attrType.isPrimitive()) {
+            if (attrType == boolean.class) {
+                return Boolean.class;
+            }
+            if (attrType == byte.class) {
+                return Byte.class;
+            }
+            if (attrType == char.class) {
+                return Character.class;
+            }
+            if (attrType == double.class) {
+                return Double.class;
+            }
+            if (attrType == float.class) {
+                return Float.class;
+            }
+            if (attrType == int.class) {
+                return Integer.class;
+            }
+            if (attrType == long.class) {
+                return Long.class;
+            }
+            if (attrType == short.class) {
+                return Short.class;
+            }
         }
         
-        if (!Serializable.class.isAssignableFrom(type) && !type.isPrimitive()) {
-            return void.class;
+        if (Date.class.isAssignableFrom(attrType) ||
+            Boolean.class.isAssignableFrom(attrType) ||
+            Character.class.isAssignableFrom(attrType) ||
+            Number.class.isAssignableFrom(attrType)) {
+            return attrType;
         }
-        
-        return type;
+
+        return String.class;
     }
     
-    private Object convertReturnValue(String name, Object v) {
+    private Object convertAttributeValue(String attrName, Object v) {
         if (v == null) {
             return null;
         }
@@ -589,15 +642,15 @@
         
         if (v instanceof Long) {
             long l = (Long) v;
-            if (name.endsWith("Time") &&
-                !propertyDescriptors.containsKey(name + "InMillis")) {
+            if (attrName.endsWith("Time") &&
+                !propertyDescriptors.containsKey(attrName + "InMillis")) {
                 if (l <= 0) {
                     return null;
                 }
                 return new Date(l);
             }
             
-            if (name.equals("id")) {
+            if (attrName.equals("id")) {
                 // ID in MINA is a unsigned 32-bit integer.
                 String id = Long.toHexString(l).toUpperCase();
                 while (id.length() < 8) {
@@ -615,16 +668,8 @@
             return convertCollection(v, new ArrayList<Object>());
         }
         
-        if (v instanceof AttributeKey) {
-            return v.toString();
-        }
-        
-        if (v instanceof IoSession) {
-            return v.toString();
-        }
-        
-        if (v instanceof IoService) {
-            return v.toString();
+        if (v instanceof Map) {
+            return convertCollection(v, new HashMap<Object, Object>());
         }
         
         if (v instanceof IoSessionDataStructureFactory ||
@@ -656,39 +701,47 @@
             return v.getClass().getName();
         }
         
-        if (v instanceof TrafficMask) {
-            TrafficMask m = (TrafficMask) v;
-            if (m.isReadable() && m.isWritable()) {
-                return "all";
-            }
-            if (m.isReadable()) {
-                return "read";
-            }
-            if (m.isWritable()) {
-                return "write";
-            }
-            return "none";
-        }
-        
-        if (v instanceof SocketAddress) {
-            PropertyEditor editor = getPropertyEditor(v.getClass());
-            if (editor != null) {
-                editor.setValue(v);
-                return editor.getAsText();
-            }
+        if (v.getClass().isPrimitive() ||
+            Date.class.isAssignableFrom(v.getClass()) ||
+            Boolean.class.isAssignableFrom(v.getClass()) ||
+            Character.class.isAssignableFrom(v.getClass()) ||
+            Number.class.isAssignableFrom(v.getClass())) {
+            return v;
         }
 
-        if (!(v instanceof Serializable)) {
-            return null;
+        PropertyEditor editor = getPropertyEditor(v.getClass());
+        if (editor != null) {
+            editor.setValue(v);
+            return editor.getAsText();
         }
-
-        return v;
+        
+        return v.toString();
     }
     
     private Object convertCollection(Object src, Collection<Object> dst) {
         Collection<?> srcCol = (Collection<?>) src;
         for (Object e: srcCol) {
-            dst.add(convertReturnValue("element", e));
+            Object convertedValue = convertAttributeValue("element", e);
+            if (e != null && convertedValue == null) {
+                convertedValue = e.toString();
+            }
+            dst.add(convertedValue);
+        }
+        return dst;
+    }
+
+    private Object convertCollection(Object src, Map<Object, Object> dst) {
+        Map<?, ?> srcCol = (Map<?, ?>) src;
+        for (Map.Entry<?, ?> e: srcCol.entrySet()) {
+            Object convertedKey = convertAttributeValue("key", e.getKey());
+            Object convertedValue = convertAttributeValue("value", e.getValue());
+            if (e.getKey() != null && convertedKey == null) {
+                convertedKey = e.getKey().toString();
+            }
+            if (e.getValue() != null && convertedValue == null) {
+                convertedKey = e.getValue().toString();
+            }
+            dst.put(convertedKey, convertedValue);
         }
         return dst;
     }