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 2013/02/27 16:59:44 UTC

svn commit: r1450821 [5/5] - in /felix/trunk/ipojo/handler/jmx: ./ doc/ jmx-handler-it/ jmx-handler-it/src/ jmx-handler-it/src/it/ jmx-handler-it/src/it/jmx-it/ jmx-handler-it/src/it/jmx-it/src/ jmx-handler-it/src/it/jmx-it/src/main/ jmx-handler-it/src...

Added: felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java?rev=1450821&view=auto
==============================================================================
--- felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java (added)
+++ felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MBeanHandler.java Wed Feb 27 15:59:42 2013
@@ -0,0 +1,668 @@
+/*
+ * 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.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.apache.felix.ipojo.FieldInterceptor;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.PrimitiveHandler;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.FieldMetadata;
+import org.apache.felix.ipojo.parser.MethodMetadata;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * This class implements iPOJO Handler. it builds the dynamic MBean from
+ * metadata.xml and exposes it to the MBean Server.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MBeanHandler extends PrimitiveHandler {
+
+    /**
+     * The name of the MBeanRegistration postDeregister method.
+     */
+    public static final String POST_DEREGISTER_METH_NAME = "postDeregister";
+
+    /**
+     * The name of the MBeanRegistration preDeregister method.
+     */
+    public static final String PRE_DEREGISTER_METH_NAME = "preDeregister";
+
+    /**
+     * The name of the MBeanRegistration postRegister method.
+     */
+    public static final String POST_REGISTER_METH_NAME = "postRegister";
+
+    /**
+     * The name of the MBeanRegistration preRegister method.
+     */
+    public static final String PRE_REGISTER_METH_NAME = "preRegister";
+
+    /**
+     * The name of the global configuration element.
+     */
+    private static final String JMX_CONFIG_ELT = "config";
+
+    /**
+     * The name of the global configuration element.
+     */
+    private static final String JMX_CONFIG_ALT_ELT = "JmxBean";
+
+    /**
+     * The name of the component object full name attribute.
+     */
+    private static final String JMX_OBJ_NAME_ELT = "objectName";
+
+    /**
+     * The name of the component object name domain attribute.
+     */
+    private static final String JMX_OBJ_NAME_DOMAIN_ELT = "domain";
+
+    /**
+     * The name of the component object name attribute.
+     */
+    private static final String JMX_OBJ_NAME_WO_DOMAIN_ELT = "name";
+
+    /**
+     * The name of the attribute indicating if the handler uses MOSGi MBean server.
+     */
+    private static final String JMX_USES_MOSGI_ELT = "usesMOSGi";
+
+    /**
+     * The name of a method element.
+     */
+    private static final String JMX_METHOD_ELT = "method";
+
+    /**
+     * The alternative name of a method element.
+     */
+    private static final String JMX_METHOD_ELT_ALT = "JmxMethod";
+
+    /**
+     * The name of the property or method name attribute.
+     */
+    private static final String JMX_NAME_ELT = "name";
+
+    /**
+     * The name of a method description attribute.
+     */
+    private static final String JMX_DESCRIPTION_ELT = "description";
+
+    /**
+     * The name of a property element.
+     */
+    private static final String JMX_PROPERTY_ELT = "property";
+
+    /**
+     * The alternative name of a property element.
+     */
+    private static final String JMX_PROPERTY_ELT_ALT = "JmxProperty";
+
+    /**
+     * The name of the field attribute.
+     */
+    private static final String JMX_FIELD_ELT = "field";
+
+    /**
+     * The name of the notification attribute.
+     */
+    private static final String JMX_NOTIFICATION_ELT = "notification";
+
+    /**
+     * The name of the rights attribute.
+     */
+    private static final String JMX_RIGHTS_ELT = "rights";
+
+    /**
+     * The instance manager. Used to store the InstanceManager instance.
+     */
+    private InstanceManager m_instanceManager;
+    /**
+     * The service registration. Used to register and unregister the Dynamic MBean.
+     */
+    private ServiceRegistration m_serviceRegistration;
+    /**
+     * Stores data when parsing metadata.xml.
+     */
+    private JmxConfigFieldMap m_jmxConfigFieldMap;
+    /**
+     * Stores the Dynamic MBean.
+     */
+    private DynamicMBeanImpl m_MBean;
+    /**
+     * Constant storing the name of the class.
+     */
+    private String m_namespace = "org.apache.felix.ipojo.handlers.jmx";
+    /**
+     * The flag used to inform if we use the MOSGi framework.
+     */
+    private boolean m_usesMOSGi;
+    /**
+     * The ObjectName used to register the MBean.
+     */
+    private ObjectName m_objectName;
+    /**
+     * The flag used to inform if the MBean is registered.
+     */
+    private boolean m_registered;
+    /**
+     * The ObjectName specified in handler configuration. It can be null.
+     */
+    private String m_completeObjNameElt;
+    /**
+     * The ObjectName without domain specified in handler configuration. It can be null.
+     */
+    private String m_objNameWODomainElt;
+
+    /**
+     * The ObjectName domain specified in handler configuration. It can be null.
+     */
+    private String m_domainElt;
+    /**
+     * The flag informing if the POJO implements the MBeanRegistration interface.
+     */
+    private boolean m_registerCallbacks;
+    /**
+     * The preRegister method of MBeanRegistration interface. It is null if POJO doesn't implement MBeanRegistration interface.
+     */
+    private MethodMetadata m_preRegisterMeth;
+    /**
+     * The postRegister method of MBeanRegistration interface. It is null if POJO doesn't implement MBeanRegistration interface.
+     */
+    private MethodMetadata m_postRegisterMeth;
+    /**
+     * The preDeregister method of MBeanRegistration interface. It is null if POJO doesn't implement MBeanRegistration interface.
+     */
+    private MethodMetadata m_preDeregisterMeth;
+    /**
+     * The postDeregister method of MBeanRegistration interface. It is null if POJO doesn't implement MBeanRegistration interface.
+     */
+    private MethodMetadata m_postDeregisterMeth;
+
+    /**
+     * Constructs the structure JmxConfigFieldMap and the Dynamic Mbean.
+     *
+     * @param metadata the component metadata
+     * @param dict the instance configuration
+     */
+    public void configure(Element metadata, Dictionary dict) {
+
+        PojoMetadata manipulation = getPojoMetadata();
+
+        m_instanceManager = getInstanceManager();
+
+        m_jmxConfigFieldMap = new JmxConfigFieldMap();
+
+        // Build the hashmap
+        Element[] mbeans = metadata.getElements(JMX_CONFIG_ELT, m_namespace);
+        if (mbeans == null || mbeans.length == 0) {
+            mbeans = metadata.getElements(JMX_CONFIG_ALT_ELT, m_namespace);
+        }
+
+        if (mbeans.length != 1) {
+            error("A component must have exactly one " + JMX_CONFIG_ELT + " or " + JMX_CONFIG_ALT_ELT + " element.");
+            error("The JMX handler configuration is ignored.");
+            return;
+        }
+
+        Element mbean = mbeans[0];
+
+        // retrieve kind of MBeanServer to use
+        m_usesMOSGi = Boolean.parseBoolean(mbean.getAttribute(JMX_USES_MOSGI_ELT));
+
+        // retrieve object name
+        m_completeObjNameElt = mbean.getAttribute(JMX_OBJ_NAME_ELT);
+        m_domainElt = mbean.getAttribute(JMX_OBJ_NAME_DOMAIN_ELT);
+        m_objNameWODomainElt = mbean.getAttribute(JMX_OBJ_NAME_WO_DOMAIN_ELT);
+
+        // test if Pojo is interested in registration callbacks
+        m_registerCallbacks = manipulation
+            .isInterfaceImplemented(MBeanRegistration.class.getName());
+        if (m_registerCallbacks) {
+            // don't need to check that methods exist, the pojo implements
+            // MBeanRegistration interface
+            String[] preRegisterParams = { MBeanServer.class.getName(),
+                    ObjectName.class.getName() };
+            m_preRegisterMeth = manipulation.getMethod(PRE_REGISTER_METH_NAME,
+                preRegisterParams);
+
+            String[] postRegisterParams = { Boolean.class.getName() };
+            m_postRegisterMeth = manipulation.getMethod(
+                POST_REGISTER_METH_NAME, postRegisterParams);
+
+            m_preDeregisterMeth = manipulation.getMethod(
+                PRE_DEREGISTER_METH_NAME, new String[0]);
+
+            m_postDeregisterMeth = manipulation.getMethod(
+                POST_DEREGISTER_METH_NAME, new String[0]);
+        }
+
+        // set property
+        Element[] attributes = mbean.getElements(JMX_PROPERTY_ELT, m_namespace);
+        Element[] attributesAlt = mbean.getElements(JMX_PROPERTY_ELT_ALT, m_namespace);
+        List<Element> listOfAttributes = new ArrayList<Element>();
+        if (attributes != null) {
+        	listOfAttributes.addAll(Arrays.asList(attributes));
+        }
+        if (attributesAlt != null) {
+        	listOfAttributes.addAll(Arrays.asList(attributesAlt));
+        }
+
+        Element[] attributesOld = mbeans[0].getElements(JMX_PROPERTY_ELT);
+        if (attributesOld != null) {
+            warn("The JMX property element should use the '" + m_namespace + "' namespace.");
+            listOfAttributes.addAll(Arrays.asList(attributesOld));
+        }
+
+        for (Element attribute : listOfAttributes) {
+            boolean notif = false;
+            String rights;
+            String name;
+            String field = attribute.getAttribute(JMX_FIELD_ELT);
+
+            if (attribute.containsAttribute(JMX_NAME_ELT)) {
+                name = attribute.getAttribute(JMX_NAME_ELT);
+            } else {
+                name = field;
+            }
+            if (attribute.containsAttribute(JMX_RIGHTS_ELT)) {
+                rights = attribute.getAttribute(JMX_RIGHTS_ELT);
+            } else {
+                rights = "r";
+            }
+
+            PropertyField property = new PropertyField(name, field, rights,
+                getTypeFromAttributeField(field, manipulation));
+
+            if (attribute.containsAttribute(JMX_NOTIFICATION_ELT)) {
+                notif = Boolean.parseBoolean(attribute
+                    .getAttribute(JMX_NOTIFICATION_ELT));
+            }
+
+            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);
+            getInstanceManager().register(manipulation.getField(field),
+                this);
+            info("property exposed:" + name + " " + field + ":"
+                    + getTypeFromAttributeField(field, manipulation) + " "
+                    + rights + ", Notif=" + notif);
+        }
+
+        // set methods
+        Element[] methods = mbean.getElements(JMX_METHOD_ELT, m_namespace);
+        Element[] methodsAlt = mbean.getElements(JMX_METHOD_ELT_ALT, m_namespace);
+        List<Element> listOfMethods = new ArrayList<Element>();
+        if (methods != null) {
+        	listOfMethods.addAll(Arrays.asList(methods));
+        }
+        if (methodsAlt != null) {
+        	listOfMethods.addAll(Arrays.asList(methodsAlt));
+        }
+
+        Element[] methodsOld = mbeans[0].getElements(JMX_PROPERTY_ELT);
+        if (methodsOld != null) {
+            warn("The JMX method element should use the '" + m_namespace + "' namespace.");
+            listOfMethods.addAll(Arrays.asList(methodsOld));
+        }
+
+        for (Element method : listOfMethods) {
+            String name = method.getAttribute(JMX_NAME_ELT);
+            if (name == null) {
+                name = method.getAttribute("method");
+            }
+            String description = null;
+            if (method.containsAttribute(JMX_DESCRIPTION_ELT)) {
+                description = method.getAttribute(JMX_DESCRIPTION_ELT);
+            }
+
+            MethodField[] meth = getMethodsFromName(name, manipulation,
+                description);
+
+            for (int j = 0; j < meth.length; j++) {
+                m_jmxConfigFieldMap.addMethodFromName(name, meth[j]);
+
+                info("method exposed:" + meth[j].getReturnType() + " " + name);
+            }
+        }
+
+    }
+
+    /**
+     * Registers the Dynamic Mbean.
+     */
+    public void start() {
+        // create the corresponding MBean
+        if (m_registerCallbacks) {
+            m_MBean = new DynamicMBeanWRegisterImpl(m_jmxConfigFieldMap,
+                m_instanceManager, m_preRegisterMeth, m_postRegisterMeth,
+                m_preDeregisterMeth, m_postDeregisterMeth);
+        } else {
+            m_MBean = new DynamicMBeanImpl(m_jmxConfigFieldMap,
+                m_instanceManager);
+        }
+
+        if (m_usesMOSGi) {
+            // use whiteboard pattern to register MBean
+
+            if (m_serviceRegistration != null) {
+                m_serviceRegistration.unregister();
+            }
+
+            // Register the ManagedService
+            BundleContext bundleContext = m_instanceManager.getContext();
+            Properties properties = new Properties();
+            try {
+                m_objectName = new ObjectName(getObjectNameString());
+
+                properties.put("jmxagent.objectName", m_objectName.toString());
+
+                m_serviceRegistration = bundleContext.registerService(
+                    javax.management.DynamicMBean.class.getName(), m_MBean,
+                    properties);
+
+                m_registered = true;
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        } else {
+            try {
+                m_objectName = new ObjectName(getObjectNameString());
+                ObjectInstance instance = ManagementFactory
+                    .getPlatformMBeanServer().registerMBean(m_MBean,
+                        m_objectName);
+
+                // we must retrieve object name used to register the MBean.
+                // It can have been changed by preRegister method of
+                // MBeanRegistration interface.
+                if (m_registerCallbacks) {
+                    m_objectName = instance.getObjectName();
+                }
+
+                m_registered = true;
+            } catch (Exception e) {
+                error("Registration of MBean failed.", e);
+            }
+        }
+    }
+
+    /**
+     * Returns the object name of the exposed component.
+     *
+     * @return the object name of the exposed component.
+     */
+    private String getObjectNameString() {
+        if (m_completeObjNameElt != null) {
+            return m_completeObjNameElt;
+        }
+
+        String domain;
+        if (m_domainElt != null) {
+            domain = m_domainElt;
+        } else {
+            domain = getPackageName(m_instanceManager.getClassName());
+        }
+
+        String name = "type=" + m_instanceManager.getClassName() + ",instance="
+                + m_instanceManager.getInstanceName();
+        if (m_objNameWODomainElt != null) {
+            name = "name=" + m_objNameWODomainElt;
+        }
+
+        StringBuffer sb = new StringBuffer();
+        if ((domain != null) && (domain.length() > 0)) {
+            sb.append(domain + ":");
+        }
+        sb.append(name);
+
+        info("Computed Objectname: " + sb.toString());
+
+        return sb.toString();
+    }
+
+    /**
+     * Extracts the package name from of given type.
+     *
+     * @param className the type name.
+     * @return the package name of the given type.
+     */
+    private String getPackageName(String className) {
+        String packageName = "";
+
+        int plotIdx = className.lastIndexOf(".");
+        if (plotIdx != -1) {
+            packageName = className.substring(0, plotIdx);
+        }
+
+        return packageName;
+    }
+
+    /**
+     * Unregisters the Dynamic Mbean.
+     */
+    public void stop() {
+        if (m_usesMOSGi) {
+            if (m_serviceRegistration != null) {
+                m_serviceRegistration.unregister();
+            }
+        } else {
+            if (m_objectName != null) {
+                try {
+                    ManagementFactory.getPlatformMBeanServer().unregisterMBean(
+                        m_objectName);
+                } catch (Exception e) {
+                    error("Unregistration of MBean failed.", e);
+                }
+                m_objectName = null;
+            }
+        }
+
+        m_MBean = null;
+        m_registered = false;
+    }
+
+    /**
+     * Called when a POJO member is modified externally.
+     *
+     * @param pojo the modified POJO object
+     * @param fieldName the name of the modified field
+     * @param value the new value of the field
+     * @see FieldInterceptor#onSet(Object, String, Object)
+     */
+    public void onSet(Object pojo, 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()) {
+                // TODO should send notif only when value has changed to a value
+                // different than the last one.
+                m_MBean.sendNotification(propertyField.getName() + " changed",
+                    propertyField.getName(), propertyField.getType(),
+                    propertyField.getValue(), value);
+            }
+            propertyField.setValue(value);
+        }
+    }
+
+    /**
+     * Called when a POJO member is read by the MBean.
+     *
+     * @param pojo the read POJO object.
+     * @param fieldName the name of the modified field
+     * @param value the old value of the field
+     * @return the (injected) value of the field
+     * @see FieldInterceptor#onGet(Object, String, Object)
+     */
+    public Object onGet(Object pojo, String fieldName, Object value) {
+
+        // Check if the field is a configurable property
+        PropertyField propertyField = (PropertyField) m_jmxConfigFieldMap
+            .getPropertyFromField(fieldName);
+        if (propertyField != null) {
+        	// Do we have a value to inject ?
+        	Object v = propertyField.getValue();
+        	if (v == null) {
+        		String type = propertyField.getType();
+    	        if ("boolean".equals(type)) { v = Boolean.FALSE; }
+    	        else if ("byte".equals(type)) { v = new Byte((byte) 0); }
+    	        else if ("short".equals(type)) { v = new Short((short) 0); }
+    	        else if ("int".equals(type)) { v = new Integer(0); }
+    	        else if ("long".equals(type)) { v = new Long(0); }
+    	        else if ("float".equals(type)) { v = new Float(0); }
+    	        else if ("double".equals(type)) { v =new Double(0); }
+    	        else if ("char".equals(type)) { v = new Character((char) 0); }
+
+    	        return v;
+    	    }
+            m_instanceManager.onSet(pojo, fieldName, propertyField.getValue());
+            return propertyField.getValue();
+        }
+        return value;
+    }
+
+    /**
+     * Gets the type from a field name.
+     *
+     * @param fieldRequire the name of the required field
+     * @param manipulation the metadata extracted from metadata.xml file
+     * @return the type of the field or {@code null} if it wasn't found
+     */
+    private static String getTypeFromAttributeField(String fieldRequire,
+            PojoMetadata manipulation) {
+
+        FieldMetadata field = manipulation.getField(fieldRequire);
+        if (field == null) {
+            return null;
+        } else {
+            return FieldMetadata.getReflectionType(field.getFieldType());
+        }
+    }
+
+    /**
+     * Gets all the methods available which get this name.
+     *
+     * @param methodName the name of the required methods
+     * @param manipulation the metadata extract from metadata.xml file
+     * @param description the description which appears in JMX console
+     * @return the array of methods with the right name
+     */
+    private MethodField[] getMethodsFromName(String methodName,
+            PojoMetadata manipulation, String description) {
+
+        MethodMetadata[] methods = manipulation.getMethods(methodName);
+        if (methods.length == 0) {
+            return null;
+        }
+
+        MethodField[] ret = new MethodField[methods.length];
+
+        if (methods.length == 1) {
+            ret[0] = new MethodField(methods[0], description);
+            return ret;
+        } else {
+            for (int i = 0; i < methods.length; i++) {
+                ret[i] = new MethodField(methods[i], description);
+            }
+            return ret;
+        }
+    }
+
+    /**
+     * Gets the JMX handler description.
+     *
+     * @return the JMX handler description.
+     * @see org.apache.felix.ipojo.Handler#getDescription()
+     */
+    public HandlerDescription getDescription() {
+        return new JMXHandlerDescription(this);
+    }
+
+    /**
+     * Returns the objectName used to register the MBean. If the MBean is not registered, return an empty string.
+     *
+     * @return the objectName used to register the MBean.
+     * @see org.apache.felix.ipojo.Handler#getDescription()
+     */
+    public String getUsedObjectName() {
+        if (m_objectName != null) {
+            return m_objectName.toString();
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Returns true if the MBean is registered.
+     *
+     * @return true if the MBean is registered.
+     */
+    public boolean isRegistered() {
+        return m_registered;
+    }
+
+    /**
+     * Returns true if the MBean must be registered thanks to white board pattern of MOSGi.
+     *
+     * @return {@code true} if the MBean must be registered thanks to white board pattern of MOSGi, false otherwise.
+     */
+    public boolean isUsesMOSGi() {
+        return m_usesMOSGi;
+    }
+
+    /**
+     * Returns true if the MOSGi framework is present on the OSGi platform.
+     *
+     * @return {@code true} if the MOSGi framework is present on the OSGi platform, false otherwise.
+     */
+    public boolean isMOSGiExists() {
+        for (Bundle bundle : m_instanceManager.getContext().getBundles()) {
+            String symbolicName = bundle.getSymbolicName();
+            if ("org.apache.felix.mosgi.jmx.agent".equals(symbolicName)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}

Added: felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java?rev=1450821&view=auto
==============================================================================
--- felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java (added)
+++ felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/MethodField.java Wed Feb 27 15:59:42 2013
@@ -0,0 +1,101 @@
+/* 
+ * 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 builds a method JMX description.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodField {
+
+    /**
+     * Stores the method description.
+     */
+    private String m_description;
+    /**
+     * Stores the method properties.
+     */
+    private MethodMetadata m_method;
+
+    /**
+     * Constructor.
+     * 
+     * @param method the method properties
+     * @param description the method description
+     */
+    public MethodField(MethodMetadata method, String description) {
+        this.m_method = method;
+        this.m_description = description;
+
+    }
+
+    /**
+     * Gets the method.
+     * @return the method
+     */
+    public MethodMetadata getMethod() {
+        return m_method;
+    }
+
+    /**
+     * Gets the description.
+     * @return the description
+     */
+    public String getDescription() {
+        return m_description;
+    }
+
+    /**
+     * Gets the name.
+     * @return the name
+     */
+    public String getName() {
+        return m_method.getMethodName();
+    }
+
+    /**
+     * Gets the parameter in JMX format.
+     * 
+     * @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/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java?rev=1450821&view=auto
==============================================================================
--- felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java (added)
+++ felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/NotificationField.java Wed Feb 27 15:59:42 2013
@@ -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 class builds the notification description structure.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class NotificationField {
+    /**
+     * The name of the notification.
+     */
+    private String m_name;
+    /**
+     * The description of the notification.
+     */
+    private String m_description;
+    /**
+     * The field of the notification.
+     */
+    private String m_field;
+
+    /**
+     * Constructor.
+     * 
+     * @param name the name of the notification
+     * @param field the field which send a notification when it is modified
+     * @param description the description 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;
+    }
+
+    /**
+     * Returns the MBeanNotificationInfo from this class.
+     * 
+     * @return the type of the field or {@code 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/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java?rev=1450821&view=auto
==============================================================================
--- felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java (added)
+++ felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/java/org/apache/felix/ipojo/handlers/jmx/PropertyField.java Wed Feb 27 15:59:42 2013
@@ -0,0 +1,196 @@
+/* 
+ * 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 class build the notification description structure.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class PropertyField {
+
+    /**
+     * The name of the notification.
+     */
+    private String m_name;
+    /**
+     *  The name of the notification.
+     */
+    private String m_field;
+    /**
+     * The name of the notification.
+     */
+    private String m_rights;
+    /**
+     * The name of the notification.
+     */
+    private String m_type;
+    /**
+     * The name of the notification.
+     */
+    private Object m_value;
+    /**
+     * The name of the notification.
+     */
+    private boolean m_notification;
+
+    /**
+     * Constructor.
+     *
+     * @param name the name of the properety
+     * @param field the 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
+        }
+    }
+
+    /**
+     * Returns the field.
+     * @return the field
+     */
+    public String getField() {
+        return m_field;
+    }
+
+    /**
+     * Modifies the field.
+     * @param field the new field
+     */
+    public void setField(String field) {
+        this.m_field = field;
+    }
+
+    /**
+     * Returns the name.
+     * @return the name
+     */
+    public String getName() {
+        return m_name;
+    }
+
+    /**
+     * Modifies the name.
+     * @param name the new name
+     */
+    public void setName(String name) {
+        this.m_name = name;
+    }
+
+    /**
+     * Returns the rights.
+     * @return the rights
+     */
+    public String getRights() {
+        return m_rights;
+    }
+
+    /**
+     * Modifies the rights.
+     * @param rights the new rights
+     */
+    public void setRights(String rights) {
+        this.m_rights = rights;
+    }
+
+    /**
+     * Returns the value.
+     * @return the value
+     */
+    public Object getValue() {
+        return m_value;
+    }
+
+    /**
+     * Modifies the value.
+     * @param value the new value
+     */
+    public void setValue(Object value) {
+        this.m_value = value;
+    }
+
+    /**
+     * Returns the type.
+     * @return the type
+     */
+    public String getType() {
+        return this.m_type;
+    }
+
+    /**
+     * Returns the description.
+     * @return the description
+     */
+    public String getDescription() {
+        //TODO Implement this method.
+        return null;
+    }
+
+    /**
+     * Returns true if this property field is readable, false otherwise.
+     * @return {@code true} if this property field is readable, {@code false} otherwise.
+     */
+    public boolean isReadable() {
+        return this.getRights().equals("r") || this.getRights().equals("w");
+    }
+
+    /**
+     * Returns true if this property field is writable, false otherwise.
+     * @return {@code true} if this property field is writable, {@code false} otherwise.
+     */
+    public boolean isWritable() {
+        return this.getRights().equals("w");
+    }
+
+    /**
+     * Returns true if this property field is notifiable, false otherwise.
+     * @return {@code true} if this property field is notifiable, {@code false} otherwise.
+     */
+    public boolean isNotifiable() {
+        return this.m_notification;
+    }
+
+    /**
+     * Modify the notifiability of this property field.
+     * @param value the new notifiability of this property field.
+     */
+    public void setNotifiable(boolean value) {
+        this.m_notification = value;
+    }
+
+    /**
+     * Is the rights is valid or not ? (ie = 'r' || 'w').
+     *
+     * @param rights string representing the rights
+     * @return boolean : return {@code true} if rights = 'r' or 'w'
+     */
+    public static boolean isRightsValid(String rights) {
+        return rights != null && (rights.equals("r") || rights.equals("w"));
+    }
+
+}

Added: felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/resources/jmx.xsd
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/resources/jmx.xsd?rev=1450821&view=auto
==============================================================================
--- felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/resources/jmx.xsd (added)
+++ felix/trunk/ipojo/handler/jmx/jmx-handler/src/main/resources/jmx.xsd Wed Feb 27 15:59:42 2013
@@ -0,0 +1,177 @@
+<!--
+	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.
+-->
+<xs:schema targetNamespace="org.apache.felix.ipojo.handlers.jmx"
+	xmlns="org.apache.felix.ipojo.handlers.jmx"
+	xmlns:xs="http://www.w3.org/2001/XMLSchema"
+	elementFormDefault="qualified">
+	<xs:element name="config" type="JMXType"></xs:element>
+
+	<xs:complexType name="JMXType">
+
+		<xs:annotation>
+			<xs:documentation>
+				Description of a JMX managed component.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:choice minOccurs="0" maxOccurs="unbounded">
+			<xs:element name="method" type="JMXMethod">
+				<xs:annotation>
+					<xs:documentation>
+						The list of methods to expose.
+					</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="property" type="JMXProperty">
+				<xs:annotation>
+					<xs:documentation>
+						The list of attributes to expose.
+					</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:choice>
+		<xs:attribute name="usesMOSGi" type="xs:boolean"
+			use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					Determines if the component must be register on the
+					MOSGi MBean server or not.
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+		<xs:attribute name="objectName" type="xs:string"
+			use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					The complete object name of the managed component.
+					The syntax of this attribute must be compliant with
+					the ObjectName syntax, detailed in the JMX
+					specification. If neither domain nor name attributes
+					are specified, the default value is determined by
+					the package, the type and the instance name of the
+					component. This attribute overrides the domain and
+					name attributes.
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+		<xs:attribute name="domain" type="xs:string" use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					The domain of the managed object (i.e., the left
+					part of the object name). This attribute must be
+					compliant with the domain syntax, as described in
+					the JMX specification.
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+		<xs:attribute name="name" type="xs:string" use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					The name property of the managed object. The value
+					of this attribute must comply with the ObjectName
+					value syntax, as described in the JMX specification.
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+
+		<xs:attribute name="preRegister" type="xs:string"
+			use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					Specifies method to carry out operations before
+					beeing registered from the MBean server. The
+					signature of the specified method must be :
+					"ObjectName preRegister(MBeanServer server,
+					ObjectName name) throws Exception".
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+		<xs:attribute name="postRegister" type="xs:string"
+			use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					Specifies method to carry out operations after
+					beeing registered from the MBean server. The
+					signature of the specified method must be : "void
+					postRegister(Boolean registrationDone)".
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+		<xs:attribute name="preDeregister" type="xs:string"
+			use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					Specifies method to carry out operations before
+					beeing unregistered from the MBean server. The
+					signature of the specified method must be : "void
+					preDeregister() throws Exception".
+				</xs:documentation>
+			</xs:annotation>
+		</xs:attribute>
+		<xs:attribute name="postDeregister" type="xs:string" use="optional">
+			<xs:annotation>
+				<xs:documentation>
+					Specifies method to carry out operations after
+					beeing unregistered from the MBean server. The
+					signature of the specified method must be : 
+					"void postDeregister()".</xs:documentation>
+			</xs:annotation></xs:attribute>
+	</xs:complexType>
+
+	<xs:complexType name="JMXProperty">
+        <xs:annotation>
+        	<xs:documentation>Description of an attribute to expose.</xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="field" type="xs:string" use="required">
+        	<xs:annotation>
+        		<xs:documentation>The name of the component's field to expose.</xs:documentation></xs:annotation></xs:attribute>
+		<xs:attribute name="name" type="xs:string" use="optional">
+			<xs:annotation>
+				<xs:documentation>The name of the property as it will appear in JMX. If unspecified, the default value is the name of the exposed field.</xs:documentation></xs:annotation></xs:attribute>
+		<xs:attribute name="rights" use="optional">
+            <xs:annotation>
+            	<xs:documentation>Specify the access permission of the exposed field.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:annotation>
+                	<xs:documentation>Access permission of an exposed field. Accepted values are "r" (read-only access, the default value) and "w" (read and write access).</xs:documentation>
+                </xs:annotation>
+                <xs:restriction base="xs:string">
+					<xs:enumeration value="r"></xs:enumeration>
+					<xs:enumeration value="w"></xs:enumeration>
+				</xs:restriction>
+			</xs:simpleType>
+		</xs:attribute>
+		<xs:attribute name="notification" type="xs:boolean" use="optional">
+			<xs:annotation>
+				<xs:documentation>Enable or disable attribute change notification sending for this property. If set to &quot;true&quot;, a notification is sent each time the value of the field changes.</xs:documentation></xs:annotation></xs:attribute>
+	</xs:complexType>
+
+	<xs:complexType name="JMXMethod">
+        <xs:annotation>
+        	<xs:documentation>Description of a method to expose.</xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="name" type="xs:string" use="required">
+        	<xs:annotation>
+        		<xs:documentation>The name of the method to expose. If multiple methods have the same name, all of them are exposed.</xs:documentation>
+        	</xs:annotation></xs:attribute>
+		<xs:attribute name="description" type="xs:string" use="optional">
+			<xs:annotation>
+				<xs:documentation>The description of the exposed method, as it will appear in JMX.</xs:documentation></xs:annotation></xs:attribute>
+	</xs:complexType>
+</xs:schema>
\ No newline at end of file

Modified: felix/trunk/ipojo/handler/jmx/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/jmx/pom.xml?rev=1450821&r1=1450820&r2=1450821&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/jmx/pom.xml (original)
+++ felix/trunk/ipojo/handler/jmx/pom.xml Wed Feb 27 15:59:42 2013
@@ -16,110 +16,100 @@
   specific language governing permissions and limitations
   under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <parent>
-    <groupId>org.apache.felix</groupId>
-    <artifactId>felix-parent</artifactId>
-    <version>1.2.1</version>
-    <relativePath>../../pom/pom.xml</relativePath>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <packaging>bundle</packaging>
-  <name>Apache Felix iPOJO JMX Handler</name>
-  <artifactId>org.apache.felix.ipojo.handler.jmx</artifactId>
-  <version>1.5.0-SNAPSHOT</version>
-  
-  <description>
-  iPOJO extension to expose instances as MBean inside a MBean Server.
-  </description>
-  <url>http://felix.apache.org/site/ipojo-jmx-handler.html</url>
-  
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.felix</groupId>
-      <artifactId>org.apache.felix.ipojo</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <version>4.0.0</version>
-    </dependency>
-  </dependencies>
-  <build>
-    <plugins>
-      <plugin>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
         <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <version>1.4.3</version>
-        <configuration>
-          <instructions>
-            <Private-Package> org.apache.felix.ipojo.handlers.jmx
-            </Private-Package>
-            <Bundle-Name>${project.name}</Bundle-Name>
-            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
-            <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
-            <Bundle-Description> iPOJO JMX Handler </Bundle-Description>
-            <Bundle-DocURL>
-              http://felix.apache.org/site/ipojo-jmx-handler.html
-            </Bundle-DocURL>
-            <Include-Resource> 
-              META-INF/LICENSE=LICENSE,
-              META-INF/NOTICE=NOTICE,
-              META-INF/DEPENDENCIES=DEPENDENCIES
-            </Include-Resource>
-          </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>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-ipojo-plugin</artifactId>
-        <version>${project.version}</version>
-        <executions>
-          <execution>
-            <goals>
-              <goal>ipojo-bundle</goal>
-            </goals>
-            <configuration>
-              <metadata>metadata.xml</metadata>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>rat-maven-plugin</artifactId>
-        <configuration>
-          <excludeSubProjects>false</excludeSubProjects>
-          <useEclipseDefaultExcludes>true</useEclipseDefaultExcludes>
-          <useMavenDefaultExcludes>true</useMavenDefaultExcludes>
-          <excludes>
-            <param>doc/**/*</param>
-            <param>maven-eclipse.xml</param>
-            <param>.checkstyle</param>
-            <param>.externalToolBuilders/*</param>
-            <param>LICENSE.asm</param>
-          </excludes>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-checkstyle-plugin</artifactId>
-        <configuration>
-          <enableRulesSummary>false</enableRulesSummary>
-          <violationSeverity>warning</violationSeverity>
-          <configLocation>http://felix.apache.org/ipojo/dev/checkstyle_ipojo.xml</configLocation>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+        <artifactId>felix-parent</artifactId>
+        <version>1.2.1</version>
+        <relativePath>../../pom/pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.apache.felix.ipojo.handler.jmx-handler-project</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <name>Apache Felix iPOJO Event Admin Handler Project</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>jmx-handler</module>
+        <module>jmx-handler-it</module>
+    </modules>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>.</directory>
+                <targetPath>META-INF</targetPath>
+                <includes>
+                    <include>LICENSE*</include>
+                    <include>NOTICE*</include>
+                    <include>DEPENDENCIES*</include>
+                </includes>
+            </resource>
+        </resources>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-assembly-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>make-assembly</id>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>single</goal>
+                                </goals>
+                                <configuration>
+                                    <descriptorRefs>
+                                        <descriptorRef>project</descriptorRef>
+                                    </descriptorRefs>
+                                    <!-- we don't want to attach all the assemblies, such as bz2 -->
+                                    <attach>false</attach>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <!-- only attach the project and bin assemblies, in tar.gz and zip flavors -->
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-assemblies</id>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>attach-artifact</goal>
+                                </goals>
+                                <configuration>
+                                    <artifacts>
+                                        <artifact>
+                                            <file>
+                                                ${project.build.directory}/${project.artifactId}-${project.version}-project.tar.gz
+                                            </file>
+                                            <classifier>project</classifier>
+                                            <type>tar.gz</type>
+                                        </artifact>
+                                        <artifact>
+                                            <file>
+                                                ${project.build.directory}/${project.artifactId}-${project.version}-project.zip
+                                            </file>
+                                            <classifier>project</classifier>
+                                            <type>zip</type>
+                                        </artifact>
+                                    </artifacts>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>