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>