Author: cziegeler
Date: Tue Aug 13 15:14:19 2013
New Revision: 1513542

URL: http://svn.apache.org/r1513542
Log:
SLING-2987 - Use service tracker for tracking HC services. This avoids all the 
nasty sync'ing of multi references

Modified:
    
sling/trunk/contrib/extensions/healthcheck/jmx/src/main/java/org/apache/sling/hc/jmx/impl/HealthCheckMBeanCreator.java

Modified: 
sling/trunk/contrib/extensions/healthcheck/jmx/src/main/java/org/apache/sling/hc/jmx/impl/HealthCheckMBeanCreator.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/jmx/src/main/java/org/apache/sling/hc/jmx/impl/HealthCheckMBeanCreator.java?rev=1513542&r1=1513541&r2=1513542&view=diff
==============================================================================
--- 
sling/trunk/contrib/extensions/healthcheck/jmx/src/main/java/org/apache/sling/hc/jmx/impl/HealthCheckMBeanCreator.java
 (original)
+++ 
sling/trunk/contrib/extensions/healthcheck/jmx/src/main/java/org/apache/sling/hc/jmx/impl/HealthCheckMBeanCreator.java
 Tue Aug 13 15:14:19 2013
@@ -17,11 +17,9 @@
  */
 package org.apache.sling.hc.jmx.impl;
 
-import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.List;
 import java.util.Map;
 
 import javax.management.DynamicMBean;
@@ -29,91 +27,83 @@ import javax.management.DynamicMBean;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
 import org.apache.sling.hc.api.HealthCheck;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.component.ComponentContext;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/** Creates an {@link HealthCheckMbean} for every {@link HealthCheckMBean} 
service */
+/**
+ * Creates an {@link HealthCheckMbean} for every {@link HealthCheckMBean} 
service
+ *
+ * TODO: What happens if two mbeans want to use the same object name (type and 
name).
+ *       We need to handle this and maybe use service ranking to resolve the 
conflict
+ * */
 @Component
-@Reference(
-        name="HealthCheck",
-        referenceInterface=HealthCheck.class, 
-        cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, 
-        policy=ReferencePolicy.DYNAMIC)
 public class HealthCheckMBeanCreator {
-    
+
     private final Logger log = LoggerFactory.getLogger(getClass());
-    private Map<ServiceReference, ServiceRegistration> registeredServices;
-    private BundleContext bundleContext;
-    private List<ServiceReference> boundRefs = new 
ArrayList<ServiceReference>();
-    
+
+    private final Map<ServiceReference, ServiceRegistration> 
registeredServices = new HashMap<ServiceReference, ServiceRegistration>();
+
+    private ServiceTracker hcTracker;
+
     @Activate
-    protected void activate(ComponentContext ctx) {
-        registeredServices = new HashMap<ServiceReference, 
ServiceRegistration>();
-        
-        final List<ServiceReference> toAdd = new ArrayList<ServiceReference>();
-        if(!boundRefs.isEmpty()) {
-            synchronized (boundRefs) {
-                toAdd.addAll(boundRefs);
-                boundRefs.clear();
+    protected void activate(final BundleContext btx) {
+        this.hcTracker = new ServiceTracker(btx, HealthCheck.class.getName(), 
new ServiceTrackerCustomizer() {
+
+            @Override
+            public synchronized void removedService(final ServiceReference 
reference, final Object service) {
+                btx.ungetService(reference);
+                unregisterHCMBean(reference);
             }
-        }
-        
-        bundleContext = ctx.getBundleContext();
-        for(ServiceReference ref : toAdd) {
-            processHealthCheckRef(ref);
-        }
+
+            @Override
+            public synchronized void modifiedService(final ServiceReference 
reference, final Object service) {
+                unregisterHCMBean(reference);
+                registerHCMBean(btx, reference, (HealthCheck)service);
+            }
+
+            @Override
+            public synchronized Object addingService(final ServiceReference 
reference) {
+                final HealthCheck hc = (HealthCheck) btx.getService(reference);
+
+                if ( hc != null ) {
+                    registerHCMBean(btx, reference, hc);
+                }
+                return hc;
+            }
+        });
+        this.hcTracker.open();
     }
-    
+
     @Deactivate
-    protected void deactivate(ComponentContext ctx) {
-        for(ServiceRegistration r : registeredServices.values()) {
-            r.unregister();
-        }
-        registeredServices = null;
-    }
-    
-    protected void bindHealthCheck(ServiceReference ref) {
-        if(bundleContext == null) {
-            // Not sure why the bundle context can still be null here, is this
-            // called before activate??
-            synchronized (boundRefs) {
-                boundRefs.add(ref);
-            }
-        } else {
-            processHealthCheckRef(ref);
+    protected void deactivate() {
+        if ( this.hcTracker != null ) {
+            this.hcTracker.close();
+            this.hcTracker = null;
         }
     }
-    
-    private void processHealthCheckRef(ServiceReference ref) {
-        final HealthCheck hc = (HealthCheck)bundleContext.getService(ref);
+
+    private void registerHCMBean(final BundleContext bundleContext, final 
ServiceReference ref, final HealthCheck hc) {
         final HealthCheckMBean mbean = new HealthCheckMBean(hc);
-        
+
         final Dictionary<String, String> mbeanProps = new Hashtable<String, 
String>();
         mbeanProps.put("jmx.objectname", "org.apache.sling.healthcheck:type=" 
+ mbean.getJmxTypeName() + ",service=" + mbean.getName());
+
         final ServiceRegistration reg = 
bundleContext.registerService(DynamicMBean.class.getName(), mbean, mbeanProps);
         registeredServices.put(ref, reg);
         log.debug("Registered {} with properties {}", mbean, mbeanProps);
     }
-    
-    protected void unbindHealthCheck(ServiceReference ref) {
-        if(registeredServices == null) {
-            log.debug("No registeredServices, nothing to unregister");
-            return;
-        }
+
+    private void unregisterHCMBean(final ServiceReference ref) {
         final ServiceRegistration reg = registeredServices.remove(ref);
-        if(reg == null) {
-            log.warn("ServiceRegistration not found for {}", ref);
-        } else {
+        if ( reg != null ) {
             reg.unregister();
-            log.debug("Ungegistered {}", reg);
+            log.debug("Ungegistered {}", ref);
         }
     }
 }
\ No newline at end of file


Reply via email to