You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2007/06/15 14:54:30 UTC

svn commit: r547667 - in /felix/sandbox/clement/jmx.handler: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/ipojo/ src/main/java/org/apache/felix/ipojo/handle...

Author: clement
Date: Fri Jun 15 05:54:29 2007
New Revision: 547667

URL: http://svn.apache.org/viewvc?view=rev&rev=547667
Log:
Initial Import of the JMX Handler allowing instances to be control remotely via JMX (thanks to the MOSGi MBean Server).

Added:
    felix/sandbox/clement/jmx.handler/   (with props)
    felix/sandbox/clement/jmx.handler/pom.xml
    felix/sandbox/clement/jmx.handler/src/
    felix/sandbox/clement/jmx.handler/src/main/
    felix/sandbox/clement/jmx.handler/src/main/java/
    felix/sandbox/clement/jmx.handler/src/main/java/org/
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/DynamicMBeanImpl.java
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/JmxConfigFieldMap.java
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java
    felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java

Propchange: felix/sandbox/clement/jmx.handler/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Jun 15 05:54:29 2007
@@ -0,0 +1,7 @@
+target
+bin
+classes
+.settings
+.project
+.classpath
+.checkstyle

Added: felix/sandbox/clement/jmx.handler/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/pom.xml?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/pom.xml (added)
+++ felix/sandbox/clement/jmx.handler/pom.xml Fri Jun 15 05:54:29 2007
@@ -0,0 +1,60 @@
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>0.9.0-incubator-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>bundle</packaging>
+  <name>JMX iPOJO Handler</name>
+  <groupId>org.apache.felix</groupId>
+  <version>0.7.1-SNAPSHOT-incubator</version>
+  <artifactId>org.apache.felix.ipojo.handler.jmx</artifactId>
+  <dependencies>
+   	<dependency>
+		<groupId>org.apache.felix</groupId>
+		<artifactId>org.osgi.core</artifactId>
+		<version>0.9.0-incubator-SNAPSHOT</version>
+	</dependency>
+	<dependency>
+		<groupId>org.apache.felix</groupId>
+		<artifactId>org.osgi.compendium</artifactId>
+		<version>0.9.0-incubator-SNAPSHOT</version>
+	</dependency>
+	<dependency>
+      <groupId>org.apache.felix</groupId> 
+      <artifactId>org.apache.felix.ipojo.metadata</artifactId> 
+      <version>0.7.1-incubator-SNAPSHOT</version> 
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId> 
+      <artifactId>org.apache.felix.ipojo</artifactId> 
+      <version>0.7.1-incubator-SNAPSHOT</version> 
+    </dependency>
+  </dependencies>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Export-Package>org.apache.felix.ipojo.handlers.jmx</Export-Package>
+            <!--<Import-Package>org.apache.felix.ipojo.util, org.apache.felix.ipojo.parser, javax.management, org.apache.felix.ipojo, org.apache.felix.ipojo.metadata, org.osgi.framework</Import-Package>-->
+            <Bundle-Name>${pom.name}</Bundle-Name>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+		<groupId>org.apache.maven.plugins</groupId>
+		<artifactId>maven-compiler-plugin</artifactId>
+		<configuration>
+		<source>1.5</source>
+		<target>1.5</target>
+		</configuration>
+	</plugin>
+    </plugins>
+  </build>
+</project>

Added: felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/DynamicMBeanImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/DynamicMBeanImpl.java?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/DynamicMBeanImpl.java (added)
+++ felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/DynamicMBeanImpl.java Fri Jun 15 05:54:29 2007
@@ -0,0 +1,386 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.ipojo.handlers.jmx;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeChangeNotification;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ReflectionException;
+import javax.management.RuntimeOperationsException;
+
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.parser.MethodMetadata;
+import org.apache.felix.ipojo.util.Callback;
+
+/** 
+ * this class implements iPOJO DynamicMBean.
+ * it builds the dynamic MBean 
+ *  
+ *  @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class DynamicMBeanImpl extends NotificationBroadcasterSupport implements DynamicMBean {
+    /** 
+     * JmxConfigDFieldMap : store the data extracted from metadata.xml.
+     */
+    private JmxConfigFieldMap m_configMap;
+    /** 
+     * InstanceManager: use to store the InstanceManager instance.
+     */
+    private InstanceManager m_instanceManager;
+    /** 
+     * MBeanInfo : class wich store the MBean Informations.
+     */
+    private MBeanInfo m_mBeanInfo;
+    /**
+     * String : constant which store the name of the class.
+     */
+    private String m_className = this.getClass().getName();
+    
+    /** 
+     * DynamicMBeanImpl : constructor.
+     * @param properties : data extracted from metadat.xml file
+     * @param instanceManager : InstanceManager instance
+     */
+    public DynamicMBeanImpl(JmxConfigFieldMap properties, InstanceManager instanceManager) {
+        m_configMap = properties;
+        m_instanceManager = instanceManager;
+        this.buildMBeanInfo();
+    }
+    
+    /** 
+     * getAttribute implements from JMX.
+     * get the value of the required attribute 
+     * @param arg0 name of required attribute
+     * @throws AttributeNotFoundException : if the attribute doesn't exist
+     * @throws MBeanException : 
+     * @throws ReflectionException : 
+     * @return  the object attribute
+     */
+    public Object getAttribute(String arg0) throws AttributeNotFoundException, MBeanException, ReflectionException {
+        PropertyField attribute = m_configMap.getPropertyFromName(arg0);
+        
+        if (attribute == null) {
+            throw new AttributeNotFoundException(arg0 + " not found");
+        } else {
+            return attribute.getValue();
+        }
+    }
+    /** 
+     * getAttributes : implement from JMX.
+     * get values of reuqired attributes 
+     * @param attributeNames : names of the required attributes
+     * @return return the list of the attribute
+     */
+    public AttributeList getAttributes(String[] attributeNames) {
+        
+        if (attributeNames == null) {
+            throw new IllegalArgumentException("attributeNames[] cannot be null");
+        }
+        
+        AttributeList resultList = new AttributeList();
+        for (int i = 0; i < attributeNames.length; i++) {
+            PropertyField propertyField = (PropertyField) m_configMap.getPropertyFromField((String) attributeNames[i]);
+            
+            if (propertyField != null) {
+                resultList.add(new Attribute(attributeNames[i], propertyField.getValue()));
+            }
+        }
+        return resultList;
+    }
+    /** 
+     * getMBeanInfo : return the MBean Class builded.
+     * @return  return MBeanInfo class constructed by buildMBeanInfo
+     */
+    public MBeanInfo getMBeanInfo() {
+        return m_mBeanInfo;
+    }
+    /** 
+     * invoke : invoke the required method on the targeted POJO.
+     * @param operationName : name of the method called
+     * @param params : parameters given to the method
+     * @param signature : determine which method called
+     * @return Object : the object return by the method
+     * @throws MBeanException :
+     * @throws ReflectionException : 
+     */
+    public Object invoke(String operationName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+
+        MethodField method = m_configMap.getMethodFromName(operationName, signature);
+        if (method != null) {
+            MethodMetadata methodCall = method.getMethod();
+            Callback mc = new Callback(methodCall, m_instanceManager);
+            try {
+                return mc.call(params);
+            } catch (NoSuchMethodException e) {
+                System.err.println("No such method!: " + operationName);
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                System.err.println("Illegal Access Exception");
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                System.err.println("Invocation Target Exception");
+                e.printStackTrace();
+            }
+        } else {
+            throw new ReflectionException(new NoSuchMethodException(
+                    operationName), "Cannot find the operation "
+                    + operationName + " in " + m_className);
+        }
+        
+        return null;
+    }
+    /** 
+     * setAttribute : change specified attribute value.
+     * @param attribute : attribute with new value to be changed
+     * @throws AttributeNotFoundException : if the requiered attribute was not found
+     * @throws InvalidAttributeValueException : the value is inccorrect type
+     * @throws MBeanException :
+     * @throws ReflectionException :
+     */
+    public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+
+        // Check attribute is not null to avoid NullPointerException later on
+        if (attribute == null) {
+            throw new RuntimeOperationsException(new IllegalArgumentException(
+                    "Attribute cannot be null"), "Cannot invoke a setter of "
+                    + m_className + " with null attribute");
+        }
+        String name = attribute.getName();
+        Object value = attribute.getValue();
+
+        if (name == null) {
+            throw new RuntimeOperationsException(new IllegalArgumentException(
+                    "Attribute name cannot be null"),
+                    "Cannot invoke the setter of " + m_className
+                            + " with null attribute name");
+        }
+        // Check for a recognized attribute name and call the corresponding
+        // setter
+        //
+        
+        PropertyField propertyField = (PropertyField) m_configMap.getPropertyFromName(name);
+        if (propertyField == null) {
+            // unrecognized attribute name:
+            throw new AttributeNotFoundException("Attribute " + name
+                    + " not found in " + m_className);
+        }
+        if (!propertyField.isWritable()) {
+            throw new InvalidAttributeValueException(
+                    "Attribute " + name + " can not be setted");
+        }
+        
+        if (value == null) {
+            try {
+                m_instanceManager.setterCallback(propertyField.getField(), null);
+            } catch (Exception e) {
+                throw new InvalidAttributeValueException(
+                        "Cannot set attribute " + name + " to null");
+            }
+        } else { // if non null value, make sure it is assignable to the attribute
+            if (true /* TODO type.class.isAssignableFrom(value.getClass())*/) {
+                //propertyField.setValue(value);
+                // setValue(attributeField.getField(),null);
+                m_instanceManager.setterCallback(propertyField.getField(), value);
+            } else {
+                throw new InvalidAttributeValueException(
+                        "Cannot set attribute " + name + " to a "
+                                + value.getClass().getName()
+                                + " object, String expected");
+            }
+        }
+
+        
+    }
+    /** 
+     * setAttributes : change all the attributes value.
+     * @param attributes : list of attribute value to be changed
+     * @return AttributeList : list of new attribute
+     */
+    public AttributeList setAttributes(AttributeList attributes) {
+//       Check attributes is not null to avoid NullPointerException later on
+        if (attributes == null) {
+            throw new RuntimeOperationsException(new IllegalArgumentException(
+                    "AttributeList attributes cannot be null"),
+                    "Cannot invoke a setter of " + m_className);
+        }
+        AttributeList resultList = new AttributeList();
+
+        // if attributeNames is empty, nothing more to do
+        if (attributes.isEmpty()) {
+            return resultList;
+        }
+        
+        // for each attribute, try to set it and add to the result list if
+        // successfull
+        for (Iterator i = attributes.iterator(); i.hasNext();) {
+            Attribute attr = (Attribute) i.next();
+            try {
+                setAttribute(attr);
+                String name = attr.getName();
+                Object value = getAttribute(name);
+                resultList.add(new Attribute(name, value));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return resultList;
+    }
+    /** 
+     * buildMBeanInfo : buil the MBean information on initilisation.
+     * this value don't change after
+     */
+    private void buildMBeanInfo() {
+        String dDescription = m_configMap.getDecription();
+        
+        // generate infos for attributes
+        MBeanAttributeInfo[] dAttributes = null;
+        
+        if (m_configMap == null) {
+            return;
+        }
+        
+        if (m_configMap.getProperties() != null) {
+            List < MBeanAttributeInfo> lAttributes = null;            
+            lAttributes = new ArrayList < MBeanAttributeInfo>();
+
+            Iterator iterator = m_configMap.getProperties().iterator();
+            while (iterator.hasNext()) {
+                PropertyField propertyField = (PropertyField) iterator.next();
+                lAttributes.add(new MBeanAttributeInfo(
+                        propertyField.getName(),
+                        propertyField.getType(),
+                        propertyField.getDescription(),
+                        propertyField.isReadable(),
+                        propertyField.isWritable(),
+                        false));                
+            }
+            dAttributes = (MBeanAttributeInfo[]) lAttributes.toArray(new MBeanAttributeInfo[ lAttributes.size() ]);
+        }
+
+
+        
+        MBeanOperationInfo[] dOperations = null;
+        if (m_configMap.getMethods() != null) {
+            
+            List < MBeanOperationInfo> lOperations = new ArrayList < MBeanOperationInfo>();
+            
+            Iterator iterator = m_configMap.getMethods().iterator();
+            while (iterator.hasNext()) {
+                MethodField[] method = (MethodField[]) iterator.next();
+                for (int i = 0 ; i < method.length ; i++) {
+                    lOperations.add(
+                            new MBeanOperationInfo(
+                                    method[i].getName(),
+                                    method[i].getDescription(),
+                                    method[i].getParams(),
+                                    method[i].getReturnType(),
+                                    MBeanOperationInfo.UNKNOWN
+                        )
+                    );
+                }
+                dOperations = (MBeanOperationInfo[]) lOperations.toArray(new MBeanOperationInfo[lOperations.size()]);
+            }
+        }
+
+        MBeanNotificationInfo[] dNotification = new MBeanNotificationInfo[0];
+        if (m_configMap.getMethods() != null) {
+                
+            List < MBeanNotificationInfo> lNotifications = new ArrayList < MBeanNotificationInfo>();
+                
+            Iterator iterator = m_configMap.getNotifications().iterator();
+            while (iterator.hasNext()) {
+                NotificationField notification = (NotificationField) iterator.next();
+                lNotifications.add(notification.getNotificationInfo());
+            }
+            dNotification = (MBeanNotificationInfo[]) lNotifications.toArray(new MBeanNotificationInfo[lNotifications.size()]);
+        }
+
+        m_mBeanInfo = new MBeanInfo(
+                this.m_className,
+                dDescription,
+                dAttributes,
+                null, // No constructor 
+                dOperations,
+                dNotification);
+    }
+
+    /** 
+     * getNotificationInfo : get the notification informations (use by JMX).
+     * @return MBeanNotificationInfo[] : structure which describe the notifications 
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        MBeanNotificationInfo[] dNotification = new MBeanNotificationInfo[0];
+        if (m_configMap.getMethods() != null) {
+                
+            List < MBeanNotificationInfo> lNotifications = new ArrayList < MBeanNotificationInfo>();
+                
+            Iterator iterator = m_configMap.getNotifications().iterator();
+            while (iterator.hasNext()) {
+                NotificationField notification = (NotificationField) iterator.next();
+                lNotifications.add(notification.getNotificationInfo());
+            }
+            dNotification = (MBeanNotificationInfo[]) lNotifications.toArray(new MBeanNotificationInfo[lNotifications.size()]);
+        }
+        return dNotification;
+    }
+    /** 
+     * sequenceNumber : use to calculate unique id to notification.
+     */
+    private int m_sequenceNumber = 0;
+    /** 
+     * sendNotification : send a notification to a subscriver.
+     * @param msg : msg to send
+     * @param attributeName : name of the attribute
+     * @param attributeType : type of the attribute
+     * @param oldValue : oldvalue of the attribute
+     * @param newValue : new value of the attribute
+     */
+    public void sendNotification(String msg, String attributeName,
+            String attributeType, Object oldValue, Object newValue) {
+
+        long timeStamp = System.currentTimeMillis();
+        
+               
+        if (newValue.equals(oldValue)) {
+            return;
+        }
+        m_sequenceNumber++;
+        Notification notification = new AttributeChangeNotification(
+                this, m_sequenceNumber, timeStamp,
+                msg, attributeName, attributeType, oldValue, newValue);
+        sendNotification(notification);
+        System.out.println("DEBUG: Notification sent");
+    }
+}

Added: felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/JmxConfigFieldMap.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/JmxConfigFieldMap.java?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/JmxConfigFieldMap.java (added)
+++ felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/JmxConfigFieldMap.java Fri Jun 15 05:54:29 2007
@@ -0,0 +1,283 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.ipojo.handlers.jmx;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/** 
+ * JmxConfigFieldMap : use to store the informations needed to build the Dynamic MBean.
+ *  
+ *  @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class JmxConfigFieldMap {
+
+    /** 
+     * m_properties : use to store the attributes exposed.
+     */
+    private Map < String, PropertyField > m_properties = new HashMap < String, PropertyField >();
+    /** 
+     * m_methods : use to store the methods exposed.
+     */
+    private Map < String, MethodField[] > m_methods = new HashMap < String, MethodField[] >();
+    /** 
+     * m_notification : use to store the notification allowed.
+     */
+    private Map < String, NotificationField > m_notifications = new HashMap < String, NotificationField >();
+    /** 
+     * m_description : description of the Mbean.
+     */
+    private String m_description;
+    
+    
+    /** 
+     * JmxConfigFieldMap : constructor.
+     */
+    public JmxConfigFieldMap() {
+        
+    }
+    
+    /** 
+     * getDescription : get the descritpion of the MBean.
+     * @return String : Decription of the MBean
+     */
+    public String getDecription() {
+        return m_description;
+    }
+    
+    /** 
+     * setDescription : set the descritpion of the MBean.
+     * @param description : String which describe the Mbean
+     */
+    public void setDescription(String description) {
+        this.m_description = description;
+    }
+    
+    /** 
+     * addPropertyFromName : add a new attribute exposed in the Mbean.
+     * @param name : name of the new property
+     * @param propertyField : Field which describe the property
+     */
+    public void addPropertyFromName(String name, PropertyField propertyField) {
+        m_properties.put(name, propertyField);
+    }
+    
+    /** 
+     * getProperties : get all of the properties exposed.
+     * @return : collection of all properties
+     */
+    public Collection getProperties() {
+        if (m_properties != null) {
+            return m_properties.values();
+        } else {
+            return null;
+        }     
+    }
+    
+    /** 
+     * getPropertyFromName : get the property by the name.
+     * @param name : name of the requiered property
+     * @return PropertyField : the field requiered or null if is not found
+     */
+    public PropertyField getPropertyFromName(String name) {
+        PropertyField prop = (PropertyField) m_properties.get(name);
+        return prop;
+    }
+    
+    /** 
+     * getPropertyFromField : get the property by the field.
+     * @param field : the requiered field
+     * @return PropertyField : 
+     */
+    public PropertyField getPropertyFromField(String field) {
+        PropertyField property = null;
+        Iterator it = m_properties.values().iterator();
+        while (it.hasNext()) {
+            PropertyField p = (PropertyField) it.next();
+            if (p.getField().compareTo(field) == 0) {
+                if (property != null) {
+                    System.err.println("an field already exist");
+                } else {
+                    property = p;
+                }
+            }
+        }
+        return property;   
+    }
+    
+    
+    /** 
+     * addMethodFromName : add a new method descriptor from its name.
+     * @param name : name of the method
+     * @param methodField : descritpion of the method
+     */
+    public void addMethodFromName(String name, MethodField methodField) {
+        MethodField[] mf;
+        if (!m_methods.containsKey(name)) {
+            mf = new MethodField[1];
+            mf[0] = methodField;
+        } else {
+            MethodField[] temp = (MethodField[]) m_methods.get(name);
+            mf = new MethodField[temp.length + 1];
+            for (int i = 0; i < temp.length; i++) {
+                mf[i] = temp[i];
+            }
+            mf[temp.length] = methodField;
+        }
+        m_methods.put(name, mf);
+    }
+    
+    /** 
+     * addMethodFromName : add new methods descriptors from one name.
+     * (the method muste have the same name but different signature).
+     * @param name : name of the method
+     * @param methodsField : descritpion of the methods
+     */
+    public void addMethodFromName(String name, MethodField[] methodsField) {
+        MethodField[] mf;
+        if (!m_methods.containsKey(name)) {
+            mf = methodsField;
+        } else {
+            MethodField[] temp = (MethodField[]) m_methods.get(name);
+            mf = new MethodField[temp.length + methodsField.length];
+            for (int i = 0; i < temp.length; i++) {
+                mf[i] = temp[i];
+            }
+            for (int i = 0; i < methodsField.length; i++) {
+                mf[i + temp.length] = methodsField[i];
+            }
+        }
+        m_methods.put(name, mf);
+    }
+    
+    /** 
+     * DynamicMBeanImpl : add methods from name and erase the older if exist.
+     * @param name : name of the method
+     * @param methodField : method to be added
+     */
+    public void overrideMethodFromName(String name, MethodField methodField) {
+        MethodField[] mf = new MethodField[1];
+        mf[0] = methodField;
+        m_methods.put(name, mf);
+    }
+    
+    /** 
+     * DynamicMBeanImpl : add methods from name and erase the older if exist.
+     * @param name : name of the method
+     * @param methodsField : array of methods to be added
+     */
+    public void overrideMethodFromName(String name, MethodField[] methodsField) {
+        m_methods.put(name, methodsField);  
+    }
+    
+    /** 
+     * getMethodFromName : return the metod(s) which are similar.
+     * @param name : name of requiered method
+     * @return MethodField[] : list of returned methods
+     */
+    public MethodField[] getMethodFromName(String name) {
+        MethodField[] prop = (MethodField[]) m_methods.get(name);
+        return prop;
+    }
+    
+    /** 
+     * getMethodFromName : get the method which the good signature.
+     * @param operationName : name of the method requiered
+     * @param signature : signature requiered
+     * @return MethodField : the method which the same signature or null if not found
+     */
+    public MethodField getMethodFromName(String operationName, String[] signature) {
+        MethodField[] methods = (MethodField[]) m_methods.get(operationName);
+        for (int i = 0; i < methods.length; i++) {
+            if (isSameSignature(signature, methods[i].getSignature())) {
+                return methods[i];
+            }
+        }
+        return null;
+    }
+    
+    /** 
+     * isSameSignature : compare two method signature.
+     * @param sig1 : first signature
+     * @param sig2 : second signature
+     * @return boolean : return true if the signature are similar
+     *                   fale else
+     */
+    private boolean isSameSignature(String[] sig1, String[] sig2) {
+        if (sig1.length != sig2.length) {
+            return false;
+        } else {
+            for (int i = 0; i < sig1.length; i++) {
+                //System.out.println(sig1[i] +" == "+ sig2[i]);
+                if (!sig1[i].equals(sig2[i])) {
+                    return false;
+                }
+            }
+            
+        }
+        return true;
+    }
+    
+    /** 
+     * getMethods : return all methods store.
+     * @return Collection : collection of methodField[]
+     */
+    public Collection getMethods() {
+        if (m_methods != null) {
+            return m_methods.values();
+        } else {
+            return null;
+        }
+    }   
+    
+    /** 
+     * addNotificationFromName : add a notification .
+     * @param name : 
+     * @param notificationField :
+     */
+    public void addNotificationFromName(String name, NotificationField notificationField) {
+        m_notifications.put(name, notificationField);
+    }
+    
+    /** 
+     * getNotificationFromName : return the notification with requiered name.
+     * @param name : name requiered
+     * @return NotificationField : return the notification if exist, null else
+     */
+    public NotificationField getNotificationFromName(String name) {
+        NotificationField prop = (NotificationField) m_notifications.get(name);
+        return prop;
+    }
+    
+    /** 
+     * getNotification : get all notifications define.
+     * @return Collection : return collection of NotificationField
+     */
+    public Collection getNotifications() {
+        if (m_notifications != null) {
+            return m_notifications.values();
+        } else {
+            return null;
+        }
+    }
+}

Added: felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java (added)
+++ felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java Fri Jun 15 05:54:29 2007
@@ -0,0 +1,245 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.ipojo.handlers.jmx;
+
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.Handler;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.FieldMetadata;
+import org.apache.felix.ipojo.parser.ManipulationMetadata;
+import org.apache.felix.ipojo.parser.MethodMetadata;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/** this class implements iPOJO Handler.
+ * it builds the dynamic MBean from metadata.xml and expose it to the MBean Server.
+ *  
+ *  @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class MBeanHandler extends Handler {
+    /** 
+     * InstanceManager: use to store the InstanceManager instance.
+     */
+    private InstanceManager m_instanceManager;
+    /**
+     * ServiceRegistration : use to register and deregister the Dynamic MBean.
+     */
+    private ServiceRegistration m_serviceRegistration;
+    /**
+     * JmxConfigFieldMap : use to store data when parsing metadata.xml.
+     */
+    private JmxConfigFieldMap m_jmxConfigFieldMap;
+    /**
+     * DynamicMBeanImpl : store the Dynamic MBean.
+     */
+    private DynamicMBeanImpl m_MBean;
+    /**
+     * String : constant which store the name of the class.
+     */
+    private String m_NAMESPACE = this.getClass().getName();
+
+    /** 
+     * configure : construct the structure JmxConfigFieldMap.and the Dynamic Mbean.
+     * @param im InstanceManager
+     * @param metadata Element
+     * @param dict Dictionnary
+     */
+    public void configure(InstanceManager im, Element metadata, Dictionary dict) {
+        
+        ManipulationMetadata manipulation = new ManipulationMetadata(metadata);
+        
+        m_instanceManager = im;
+
+
+        m_jmxConfigFieldMap = new JmxConfigFieldMap();
+
+        // Build the hashmap
+        Element[] mbeans = metadata.getElements("config", m_NAMESPACE);
+
+        if (mbeans.length != 1) { return; }
+        
+       
+        
+        // set property 
+        Element[] attributes = mbeans[0].getElements("property");
+        String[] fields = new String[attributes.length];
+        for (int i = 0 ; i < attributes.length ; i++) {
+            boolean notif = false;
+            String rights;
+            String name;
+            String field = attributes[i].getAttribute("field");
+            
+            if (attributes[i].containsAttribute("name")) {
+                name = attributes[i].getAttribute("name");
+            } else {
+                name = field;
+            }
+            if (attributes[i].containsAttribute("rights")) {
+                rights = attributes[i].getAttribute("rights");
+            } else {
+                rights = "w";
+            }
+            
+            PropertyField property = new PropertyField(name, field, rights, getTypeFromAttributeField(field, manipulation));
+            
+            if (attributes[i].containsAttribute("notification")) {
+                notif = Boolean.parseBoolean(attributes[i].getAttribute("notification"));
+            }
+            
+            property.setNotifiable(notif);
+            
+            if (notif) {
+                //add the new notifiable property in structure
+                NotificationField notification = new NotificationField(name, this.getClass().getName() + "." + field, null);
+                m_jmxConfigFieldMap.addNotificationFromName(name, notification);
+            }
+            m_jmxConfigFieldMap.addPropertyFromName(name, property);
+            fields[i] = field;
+            System.out.println("DEBUG: property exposed:" + name + " " + field + ":" 
+                    + getTypeFromAttributeField(field, manipulation) + " " + rights 
+                    + ", Notif=" + notif);
+        }
+        
+        //set methods 
+        Element[] methods = mbeans[0].getElements("method");
+        for (int i = 0 ; i < methods.length ; i++) {
+            String name = methods[i].getAttribute("name");
+            String description = null;
+            if (methods[i].containsAttribute("description")) {
+                description = methods[i].getAttribute("description");
+            }
+            
+            MethodField[] method = getMethodsFromName(name, manipulation, description);
+            
+            for (int j = 0 ; j < method.length ; j++) {
+                m_jmxConfigFieldMap.addMethodFromName(name, method[j]);
+            
+                System.out.println("DEBUG: method exposed:" + method[j].getReturnType() + " " + name);
+            }
+        }
+       
+        m_instanceManager.register(this, fields);
+        
+    }
+    /**
+     * start : register the Dynamic Mbean.
+     */
+    public void start() {
+//      create the corresponding MBean
+        m_MBean = new DynamicMBeanImpl(m_jmxConfigFieldMap, m_instanceManager);
+        if (m_serviceRegistration != null) { m_serviceRegistration.unregister(); }
+
+        // Register the ManagedService
+        BundleContext bundleContext = m_instanceManager.getContext();
+
+        m_serviceRegistration = bundleContext.registerService(javax.management.DynamicMBean.class.getName(), m_MBean, new Properties());
+    }
+
+    /** 
+     * stop : deregister the Dynamic Mbean.
+     */
+    public void stop() {
+        if (m_serviceRegistration != null) { m_serviceRegistration.unregister(); }
+        
+        
+    }
+    
+    
+    /** 
+     * setterCallback : call when a POJO member is modified externally.
+     * @param fieldName : name of the modified field 
+     * @param value     : new value of the field
+     */
+    public void setterCallback(String fieldName, Object value) {
+        // Check if the field is a configurable property
+
+        PropertyField propertyField = (PropertyField) m_jmxConfigFieldMap.getPropertyFromField(fieldName);
+        if (propertyField != null) {
+            if (propertyField.isNotifiable()) {
+                                            
+                m_MBean.sendNotification(propertyField.getName() + " changed", propertyField.getName(),
+                                         propertyField.getType(), propertyField.getValue(), value);
+            }
+            propertyField.setValue(value);
+        }
+    }
+
+    /** 
+     * getterCallback : call when a POJO member is modified by the MBean.
+     * @param fieldName : name of the modified field 
+     * @param value     : old value of the field
+     * @return          : new value of the field
+     */
+    public Object getterCallback(String fieldName, Object value) {
+        // Check if the field is a configurable property
+        PropertyField propertyField = (PropertyField) m_jmxConfigFieldMap.getPropertyFromField(fieldName);
+        if (propertyField != null) { return propertyField.getValue(); }
+        return value;
+    }
+    
+    /** 
+     * getTypeFromAttributeField : get the type from a field name.
+     * @param fieldRequire : name of the requiered field 
+     * @param manipulation : metadata extract from metadata.xml file
+     * @return          : type of the field or null if it wasn't found
+     */
+    private static String getTypeFromAttributeField(String fieldRequire, ManipulationMetadata manipulation) {
+        
+        FieldMetadata field = manipulation.getField(fieldRequire);
+        if (field == null) {
+            return null;
+        } else {
+            return field.getReflectionType();
+        }
+    }
+    
+    /** 
+     * getMethodsFromName : get all the methods available which get this name.
+     * @param methodName : name of the requiered methods
+     * @param manipulation : metadata extract from metadata.xml file
+     * @param description  : description which appears in jmx console
+     * @return          : array of methods with the right name
+     */
+    private MethodField[] getMethodsFromName(String methodName, ManipulationMetadata manipulation, String description) {
+        
+        MethodMetadata[] fields = manipulation.getMethods(methodName);
+        if (fields.length == 0) {
+            return null;
+        }
+        
+        MethodField[] ret = new MethodField[fields.length];
+        
+        if (fields.length == 1) {
+            ret[0] = new MethodField(fields[0], description);
+            return ret;
+        } else {
+            for (int i = 0 ; i < fields.length ; i++) {
+                ret[i] = new MethodField(fields[i], description);
+            }
+            return ret;
+        }
+    }
+    
+
+}

Added: felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java (added)
+++ felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java Fri Jun 15 05:54:29 2007
@@ -0,0 +1,86 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.ipojo.handlers.jmx;
+
+import javax.management.MBeanParameterInfo;
+
+import org.apache.felix.ipojo.parser.MethodMetadata;
+
+/** 
+ * this class build a method JMX description.
+ *  
+ *  @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class MethodField {
+
+    /** 
+     * m_description : store the method descritpion.
+     */
+    private String m_description;
+    /** 
+     * m_method : store the method properties.
+     */
+    private MethodMetadata m_method;
+    
+    /** 
+     * MethodField : constructor.
+     * @param method : the metod properties
+     * @param description : thes method description
+     */
+    public MethodField(MethodMetadata method, String description) {
+        this.m_method = method;
+        this.m_description = description;
+    
+    }
+    
+
+    public MethodMetadata getMethod() {
+        return m_method;
+    }
+
+    public String getDescription() {
+        return m_description;
+    }
+
+    public String getName() {
+        return m_method.getMethodName();
+    }
+    
+    /** 
+     * getParams : get the parameter in JMX format.
+     * @return MBeanParameterInfo : return info on JMX format
+     */
+    public MBeanParameterInfo[] getParams() {
+        MBeanParameterInfo[] mbean = new MBeanParameterInfo[m_method.getMethodArguments().length];
+        for (int i = 0; i < m_method.getMethodArguments().length; i++) {
+            mbean[i] = new MBeanParameterInfo("arg" + i, m_method.getMethodArguments()[i], null);
+        }
+        return mbean;
+    }
+
+    public String[] getSignature() {
+        return m_method.getMethodArguments();
+    }
+    
+    public String getReturnType() {
+        return m_method.getMethodReturn();
+    }
+
+}

Added: felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java (added)
+++ felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java Fri Jun 15 05:54:29 2007
@@ -0,0 +1,69 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.ipojo.handlers.jmx;
+
+import javax.management.MBeanNotificationInfo;
+
+/** 
+ * this calss build the notification descritpion structure.
+ *  
+ *  @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class NotificationField {
+    /** 
+     * m_name : name of the notification.
+     */
+    private String m_name;
+    /** 
+     * m_description : description of the notification.
+     */
+    private String m_description;
+    /** 
+     * m_description : field of the notification.
+     */
+    private String m_field;
+    
+    /** 
+     * NotificationField : constructor.
+     * @param name : name of the notification 
+     * @param field : field which send a notification when it is modified
+     * @param description : descritpion which appears in jmx console
+     */
+    
+    public NotificationField(String name, String field, String description) {
+        this.m_name = name;
+        this.m_field = field;
+        this.m_description = description;
+    }
+
+    /** 
+     * getNotificationInfo : return the MBeanNotificationInfo from this class.
+     * @return          : type of the field or null if it wasn't found
+     */
+    public MBeanNotificationInfo getNotificationInfo() {
+        String[] notificationTypes = new String[1];
+        notificationTypes[0] = m_field;
+        MBeanNotificationInfo mbni = new MBeanNotificationInfo(
+                    notificationTypes,
+                    m_name,
+                    m_description);
+        return mbni;
+    }
+}

Added: felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java?view=auto&rev=547667
==============================================================================
--- felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java (added)
+++ felix/sandbox/clement/jmx.handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java Fri Jun 15 05:54:29 2007
@@ -0,0 +1,131 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.ipojo.handlers.jmx;
+
+/** 
+ * this calss build the notification descritpion structure.
+ *  
+ *  @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class PropertyField {
+
+    /** 
+     * m_name : name of the notification.
+     */
+    private String m_name;
+    /** 
+     * m_name : name of the notification.
+     */
+    private String m_field;
+    /** 
+     * m_name : name of the notification.
+     */
+    private String m_rights;
+    /** 
+     * m_name : name of the notification.
+     */
+    private String m_type;
+    /** 
+     * m_name : name of the notification.
+     */
+    private Object m_value;
+    /** 
+     * m_name : name of the notification.
+     */
+    private boolean m_notification = false;
+    
+    /** 
+     * PropertyField : constructor.
+     * @param name : name of the properety 
+     * @param field : field which send a notification when it is modified
+     * @param rights : the rights of the attribute (ie: 'r' or 'w')
+     * @param type : the type of the attribute
+     */
+    public PropertyField(String name, String field, String rights, String type) {
+        this.setName(name);
+        this.setField(field);
+        this.m_type = type;
+        if (isRightsValid(rights)) {
+            this.setRights(rights);
+        } else {
+            this.setField("r"); //default rights is read only
+        }
+    }
+    
+    public String getField() {
+        return m_field;
+    }
+    public void setField(String field) {
+        this.m_field = field;
+    }
+    public String getName() {
+        return m_name;
+    }
+    public void setName(String name) {
+        this.m_name = name;
+    }
+    public String getRights() {
+        return m_rights;
+    }
+    public void setRights(String rights) {
+        this.m_rights = rights;
+    }
+    public Object getValue() {
+        return m_value;
+    }
+    public void setValue(Object value) {
+        this.m_value = value;
+    }
+
+    public String getType() {
+        return this.m_type;
+    }
+
+    public String getDescription() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public boolean isReadable() {
+        return this.getRights().equals("r") || this.getRights().equals("w");
+    }
+
+    public boolean isWritable() {
+        return  this.getRights().equals("w");
+    }
+    
+    public boolean isNotifiable() {
+        return this.m_notification;
+    }
+    
+    public void setNotifiable(boolean value) {
+        this.m_notification = value;
+    }
+    
+    /** 
+     * isRightsValid : return is the rights is valid or not (ie = 'r' || 'w').
+     * @param rights :  string represents the rights
+     * @return boolean : return true if rights = 'r' or 'w'
+     */
+    public static boolean isRightsValid(String rights) {
+        return rights != null && (rights.equals("r") || rights.equals("w"));
+    }
+    
+}