You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2010/09/24 16:59:25 UTC

svn commit: r1000895 - in /incubator/aries/trunk/jmx: jmx-blueprint-api/src/main/java/org/apache/aries/jmx/blueprint/ jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/ jmx-bundle/ jmx-core/

Author: gnodet
Date: Fri Sep 24 14:59:24 2010
New Revision: 1000895

URL: http://svn.apache.org/viewvc?rev=1000895&view=rev
Log:
[ARIES-426] The Blueprint JMX layer should send notifications for each blueprint event

Added:
    incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/RegistrableStandardEmitterMBean.java
Removed:
    incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/RegistrationStandardMBean.java
Modified:
    incubator/aries/trunk/jmx/jmx-blueprint-api/src/main/java/org/apache/aries/jmx/blueprint/BlueprintStateMBean.java
    incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/Activator.java
    incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/BlueprintState.java
    incubator/aries/trunk/jmx/jmx-bundle/pom.xml
    incubator/aries/trunk/jmx/jmx-core/pom.xml

Modified: incubator/aries/trunk/jmx/jmx-blueprint-api/src/main/java/org/apache/aries/jmx/blueprint/BlueprintStateMBean.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-blueprint-api/src/main/java/org/apache/aries/jmx/blueprint/BlueprintStateMBean.java?rev=1000895&r1=1000894&r2=1000895&view=diff
==============================================================================
--- incubator/aries/trunk/jmx/jmx-blueprint-api/src/main/java/org/apache/aries/jmx/blueprint/BlueprintStateMBean.java (original)
+++ incubator/aries/trunk/jmx/jmx-blueprint-api/src/main/java/org/apache/aries/jmx/blueprint/BlueprintStateMBean.java Fri Sep 24 14:59:24 2010
@@ -29,6 +29,9 @@ import javax.management.openmbean.Tabula
 
 /**
  * This MBean provides the management interface to the OSGi Blueprint Service.
+ *
+ * This MBean also emits events that clients can use to get notified of the
+ * changes in the blueprint containers state in the framework.
  * 
  * @version $Revision$
  */
@@ -190,8 +193,7 @@ public interface BlueprintStateMBean {
     /**
      * Returns all the last events associated with the blueprint bundles.
      * 
-     * @param bundleId The bundle id of a blueprint bundle
-     * @return the tabular representation of all the last events associated with the blueprint bundles see {@link #OSGI_BLUEPRINT_EVENTS_TYPE} 
+     * @return the tabular representation of all the last events associated with the blueprint bundles see {@link #OSGI_BLUEPRINT_EVENTS_TYPE}
      * @throws IOException if the operation fails
      */ 
     public TabularData getLastEvents() throws IOException;

Modified: incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/Activator.java?rev=1000895&r1=1000894&r2=1000895&view=diff
==============================================================================
--- incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/Activator.java (original)
+++ incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/Activator.java Fri Sep 24 14:59:24 2010
@@ -138,7 +138,7 @@ public class Activator implements Bundle
         // create BlueprintStateMBean
         /* the StardardMBean does not implement the MBeanRegistration in jdk1.5 */
         try {
-            blueprintState = new RegistrationStandardMBean(new BlueprintState(bundleContext), BlueprintStateMBean.class);
+            blueprintState = new RegistrableStandardEmitterMBean(new BlueprintState(bundleContext), BlueprintStateMBean.class);
         } catch (NotCompliantMBeanException e) {
             LOGGER.error("Unable to create StandardMBean for BlueprintState", e);
             return;

Modified: incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/BlueprintState.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/BlueprintState.java?rev=1000895&r1=1000894&r2=1000895&view=diff
==============================================================================
--- incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/BlueprintState.java (original)
+++ incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/BlueprintState.java Fri Sep 24 14:59:24 2010
@@ -21,9 +21,16 @@ package org.apache.aries.jmx.blueprint.i
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanRegistration;
 import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
 import javax.management.ObjectName;
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.TabularData;
@@ -35,8 +42,15 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.blueprint.container.BlueprintEvent;
 import org.osgi.service.blueprint.container.BlueprintListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BlueprintState extends NotificationBroadcasterSupport implements BlueprintStateMBean, MBeanRegistration {
+
+    // notification type description
+    public static String BLUEPRINT_EVENT = "org.osgi.blueprint.event";
 
-public class BlueprintState implements BlueprintStateMBean, MBeanRegistration {
+    private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintState.class);
 
     private BundleContext context;
 
@@ -44,21 +58,27 @@ public class BlueprintState implements B
 
     private Map<Long, CompositeData> dataMap = new HashMap<Long, CompositeData>();
 
+    private ExecutorService eventDispatcher;
+
+    private AtomicInteger notificationSequenceNumber = new AtomicInteger(1);
+
+    private AtomicInteger registrations = new AtomicInteger(0);
+
     public BlueprintState(BundleContext context) {
         this.context = context;
     }
 
     public synchronized long[] getBlueprintBundleIds() throws IOException {
-        Long[] bundleIdKeys = dataMap.keySet().toArray(new Long[0]);
+        Long[] bundleIdKeys = dataMap.keySet().toArray(new Long[dataMap.size()]);
         long[] bundleIds = new long[bundleIdKeys.length];
         for (int i = 0; i < bundleIdKeys.length; i++) {
-            bundleIds[i] = bundleIdKeys[i].longValue();
+            bundleIds[i] = bundleIdKeys[i];
         }
         return bundleIds;
     }
 
     public synchronized CompositeData getLastEvent(long bundleId) throws IOException {
-        return dataMap.get(Long.valueOf(bundleId));
+        return dataMap.get(bundleId);
     }
 
     public synchronized TabularData getLastEvents() throws IOException {
@@ -73,30 +93,87 @@ public class BlueprintState implements B
     }
 
     public void postRegister(Boolean registrationDone) {
-        BlueprintListener listener = new BlueprintStateListener();
         // reg listener
-        listenerReg = context.registerService(BlueprintListener.class.getName(), listener, null);
+        if (registrationDone && registrations.incrementAndGet() == 1) {
+            BlueprintListener listener = new BlueprintStateListener();
+            eventDispatcher = Executors.newSingleThreadExecutor(new JMXThreadFactory("JMX OSGi Blueprint State Event Dispatcher"));
+            listenerReg = context.registerService(BlueprintListener.class.getName(), listener, null);
+        }
     }
 
     public void preDeregister() throws Exception {
-        // deregister Listener
-        try{
-            listenerReg.unregister();
-        }catch(Exception e){
-            e.printStackTrace();
-        }
+        // no op
     }
 
     public void postDeregister() {
-        // no op
+        if (registrations.decrementAndGet() < 1) {
+            try {
+                listenerReg.unregister();
+            } catch(Exception e) {
+                // ignore
+            }
+            if (eventDispatcher != null) {
+                eventDispatcher.shutdown(); 
+            }
+        }
+    }
+
+    protected synchronized void onEvent(BlueprintEvent event) {
+        CompositeData data = new OSGiBlueprintEvent(event).asCompositeData();
+        dataMap.put(event.getBundle().getBundleId(), data);
+
+        if (!event.isReplay()) {
+            final Notification notification = new Notification(EVENT_TYPE, OBJECTNAME,
+                    notificationSequenceNumber.getAndIncrement());
+            try {
+                notification.setUserData(data);
+                eventDispatcher.submit(new Runnable() {
+                    public void run() {
+                        sendNotification(notification);
+                    }
+                });
+            } catch (RejectedExecutionException re) {
+                LOGGER.warn("Task rejected for JMX Notification dispatch of event ["
+                        + event + "] - Dispatcher may have been shutdown");
+            } catch (Exception e) {
+                LOGGER.warn("Exception occured on JMX Notification dispatch for event [" + event + "]", e);
+            }
+        }
+    }
+
+    /**
+     * @see javax.management.NotificationBroadcasterSupport#getNotificationInfo()
+     */
+    @Override
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        String[] types = new String[] { BLUEPRINT_EVENT };
+        String name = Notification.class.getName();
+        String description = "A BlueprintEvent issued from the Blueprint Extender describing a blueprint bundle lifecycle change";
+        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
+        return new MBeanNotificationInfo[] { info };
     }
 
     private class BlueprintStateListener implements BlueprintListener {
-        public synchronized void blueprintEvent(BlueprintEvent event) {
-            CompositeData data = new OSGiBlueprintEvent(event).asCompositeData();
-            dataMap.put(Long.valueOf(event.getBundle().getBundleId()), data);
+        public void blueprintEvent(BlueprintEvent event) {
+            onEvent(event);
         }
 
     }
 
+    public static class JMXThreadFactory implements ThreadFactory {
+        private final ThreadFactory factory = Executors.defaultThreadFactory();
+        private final String name;
+
+        public JMXThreadFactory(String name) {
+            this.name = name;
+        }
+
+        public Thread newThread(Runnable r) {
+            final Thread t = factory.newThread(r);
+            t.setName(name);
+            t.setDaemon(true);
+            return t;
+        }
+    }
+
 }

Added: incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/RegistrableStandardEmitterMBean.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/RegistrableStandardEmitterMBean.java?rev=1000895&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/RegistrableStandardEmitterMBean.java (added)
+++ incubator/aries/trunk/jmx/jmx-blueprint-core/src/main/java/org/apache/aries/jmx/blueprint/impl/RegistrableStandardEmitterMBean.java Fri Sep 24 14:59:24 2010
@@ -0,0 +1,143 @@
+/**
+ *  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.aries.jmx.blueprint.impl;
+
+import javax.management.*;
+
+/**
+ * The <code>StandardMBean</code> does not appear to delegate correctly to the underlying MBean implementation. Due to
+ * issues surrounding the <code>MBeanRegistration</code> callback methods and <code>NotificationEmmitter</code> methods,
+ * this subclass was introduced to force the delegation
+ * 
+ * @version $Rev$ $Date$
+ */
+public class RegistrableStandardEmitterMBean extends StandardMBean implements MBeanRegistration, NotificationEmitter {
+
+    public <T> RegistrableStandardEmitterMBean(T impl, Class<T> intf) throws NotCompliantMBeanException {
+        super(impl, intf);
+    }
+
+    /**
+     * @see javax.management.StandardMBean#getMBeanInfo()
+     */
+    public MBeanInfo getMBeanInfo() {
+        MBeanInfo mbeanInfo = super.getMBeanInfo();
+        if (mbeanInfo != null) {
+            MBeanNotificationInfo[] notificationInfo;
+            Object impl = getImplementation();
+            if (impl instanceof NotificationEmitter) {
+                notificationInfo = ((NotificationEmitter) (impl)).getNotificationInfo();
+            } else {
+                notificationInfo = new MBeanNotificationInfo[0];
+            }
+            mbeanInfo = new MBeanInfo(mbeanInfo.getClassName(), mbeanInfo.getDescription(), mbeanInfo.getAttributes(),
+                    mbeanInfo.getConstructors(), mbeanInfo.getOperations(), notificationInfo);
+        }
+        return mbeanInfo;
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#postDeregister()
+     */
+    public void postDeregister() {
+        Object impl = getImplementation();
+        if (impl instanceof MBeanRegistration) {
+            ((MBeanRegistration) impl).postDeregister();
+        }
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#postRegister(Boolean)
+     */
+    public void postRegister(Boolean registrationDone) {
+        Object impl = getImplementation();
+        if (impl instanceof MBeanRegistration) {
+            ((MBeanRegistration) impl).postRegister(registrationDone);
+        }
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#preDeregister()
+     */
+    public void preDeregister() throws Exception {
+        Object impl = getImplementation();
+        if (impl instanceof MBeanRegistration) {
+            ((MBeanRegistration) impl).preDeregister();
+        }
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName)
+     */
+    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
+        ObjectName result = name;
+        Object impl = getImplementation();
+        if (impl instanceof MBeanRegistration) {
+            result = ((MBeanRegistration) impl).preRegister(server, name);
+        }
+        return result;
+    }
+
+    /**
+     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener,
+     *      javax.management.NotificationFilter, Object)
+     */
+    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
+            throws ListenerNotFoundException {
+        Object impl = getImplementation();
+        if (impl instanceof NotificationEmitter) {
+            ((NotificationEmitter) (impl)).removeNotificationListener(listener, filter, handback);
+        }
+    }
+
+    /**
+     * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener,
+     *      javax.management.NotificationFilter, Object)
+     */
+    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
+            throws IllegalArgumentException {
+        Object impl = getImplementation();
+        if (impl instanceof NotificationEmitter) {
+            ((NotificationEmitter) (impl)).addNotificationListener(listener, filter, handback);
+        }
+    }
+
+    /**
+     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        MBeanNotificationInfo[] result;
+        Object impl = getImplementation();
+        if (impl instanceof NotificationEmitter) {
+            result = ((NotificationEmitter) (impl)).getNotificationInfo();
+        } else {
+            result = new MBeanNotificationInfo[0];
+        }
+        return result;
+    }
+
+    /**
+     * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
+     */
+    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
+        Object impl = getImplementation();
+        if (impl instanceof NotificationEmitter) {
+            ((NotificationEmitter) (impl)).removeNotificationListener(listener);
+        }
+    }
+
+}

Modified: incubator/aries/trunk/jmx/jmx-bundle/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-bundle/pom.xml?rev=1000895&r1=1000894&r2=1000895&view=diff
==============================================================================
--- incubator/aries/trunk/jmx/jmx-bundle/pom.xml (original)
+++ incubator/aries/trunk/jmx/jmx-bundle/pom.xml Fri Sep 24 14:59:24 2010
@@ -43,7 +43,8 @@
             org.apache.aries.jmx.codec;version="${project.version}"
         </aries.osgi.export>
         <aries.osgi.import>
-            !org.apache.aries.jmx*,
+            !org.apache.aries*,
+            !org.osgi.service.framework,
             org.osgi.framework;version="1.5.0",
             org.osgi.service.cm;version="1.3.0";resolution:="optional",
             org.osgi.service.permissionadmin;version="1.2.0";resolution:="optional",
@@ -59,11 +60,15 @@
             *
         </aries.osgi.import>
         <aries.osgi.private.pkg>
+            org.apache.aries.util*,
             org.apache.aries.jmx*
         </aries.osgi.private.pkg>
         <aries.osgi.import.service>
             javax.management.MBeanServer
         </aries.osgi.import.service>
+        <aries.osgi.failok>
+            true
+        </aries.osgi.failok>
     </properties>
 
     <dependencies>

Modified: incubator/aries/trunk/jmx/jmx-core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/pom.xml?rev=1000895&r1=1000894&r2=1000895&view=diff
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/pom.xml (original)
+++ incubator/aries/trunk/jmx/jmx-core/pom.xml Fri Sep 24 14:59:24 2010
@@ -77,15 +77,14 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.aries</groupId>
+            <artifactId>org.apache.aries.util</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-all</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <artifactId>org.apache.aries.util</artifactId>
-            <groupId>org.apache.aries</groupId>
-            <scope>provided</scope>
-        </dependency>
     </dependencies>
 
  </project>