Fix CS warnings in blueprint and enable enforcement
[controller.git] / opendaylight / blueprint / src / main / java / org / opendaylight / controller / blueprint / ext / AbstractDependentComponentFactoryMetadata.java
index bdcc1ee86d261d6c05e9c4c2cc60f0875988ea68..c55fa0ce913147b8d554a40693ededf97359aa10 100644 (file)
@@ -13,16 +13,21 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
+import javax.annotation.Nullable;
 import org.apache.aries.blueprint.di.AbstractRecipe;
 import org.apache.aries.blueprint.di.ExecutionContext;
 import org.apache.aries.blueprint.di.Recipe;
 import org.apache.aries.blueprint.ext.DependentComponentFactoryMetadata;
 import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.opendaylight.controller.blueprint.BlueprintContainerRestartService;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.blueprint.container.ComponentDefinitionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
+ * Abstract base class for a DependentComponentFactoryMetadata implementation.
+ *
  * @author Thomas Pantelis
  */
 abstract class AbstractDependentComponentFactoryMetadata implements DependentComponentFactoryMetadata {
@@ -30,10 +35,12 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
     private final String id;
     private final AtomicBoolean started = new AtomicBoolean();
     private final AtomicBoolean satisfied = new AtomicBoolean();
+    private final AtomicBoolean restarting = new AtomicBoolean();
     private final List<StaticServiceReferenceRecipe> serviceRecipes = new ArrayList<>();
     private volatile ExtendedBlueprintContainer container;
     private volatile SatisfactionCallback satisfactionCallback;
     private volatile String failureMessage;
+    private volatile Throwable failureCause;
     private volatile String dependendencyDesc;
 
     protected AbstractDependentComponentFactoryMetadata(String id) {
@@ -65,10 +72,13 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
         return satisfied.get();
     }
 
-    protected abstract void startTracking();
-
     protected void setFailureMessage(String failureMessage) {
+        setFailure(failureMessage, null);
+    }
+
+    protected void setFailure(String failureMessage, Throwable failureCause) {
         this.failureMessage = failureMessage;
+        this.failureCause = failureCause;
     }
 
     protected void setDependendencyDesc(String dependendencyDesc) {
@@ -80,13 +90,18 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
     }
 
     protected void setSatisfied() {
-        satisfied.set(true);
-        satisfactionCallback.notifyChanged();
+        if (satisfied.compareAndSet(false, true)) {
+            satisfactionCallback.notifyChanged();
+        }
     }
 
     protected void retrieveService(String name, Class<?> interfaceClass, Consumer<Object> onServiceRetrieved) {
+        retrieveService(name, interfaceClass.getName(), onServiceRetrieved);
+    }
+
+    protected void retrieveService(String name, String interfaceName, Consumer<Object> onServiceRetrieved) {
         StaticServiceReferenceRecipe recipe = new StaticServiceReferenceRecipe(getId() + "-" + name,
-                container, interfaceClass.getName());
+                container, interfaceName);
         setDependendencyDesc(recipe.getOsgiFilter());
         serviceRecipes.add(recipe);
 
@@ -94,20 +109,19 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
     }
 
     protected final String logName() {
-        return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") +
-                " (" + id + ")";
+        return (container != null ? container.getBundleContext().getBundle().getSymbolicName() : "") + " (" + id + ")";
     }
 
     @Override
-    public void init(ExtendedBlueprintContainer container) {
-        this.container = container;
+    public void init(ExtendedBlueprintContainer newContainer) {
+        this.container = newContainer;
 
         log.debug("{}: In init", logName());
     }
 
     protected void onCreate() throws ComponentDefinitionException {
-        if(failureMessage != null) {
-            throw new ComponentDefinitionException(failureMessage);
+        if (failureMessage != null) {
+            throw new ComponentDefinitionException(failureMessage, failureCause);
         }
 
         // The following code is a bit odd so requires some explanation. A little background... If a bean
@@ -137,7 +151,7 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
         executionContext.removePartialObject(id);
 
         Recipe myRecipe = executionContext.getRecipe(id);
-        if(myRecipe instanceof AbstractRecipe) {
+        if (myRecipe instanceof AbstractRecipe) {
             log.debug("{}: setPrototype to false", logName());
             ((AbstractRecipe)myRecipe).setPrototype(false);
         } else {
@@ -145,15 +159,17 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
         }
     }
 
+    protected abstract void startTracking();
+
     @Override
-    public final void startTracking(final SatisfactionCallback satisfactionCallback) {
-        if(!started.compareAndSet(false, true)) {
+    public final void startTracking(final SatisfactionCallback newSatisfactionCallback) {
+        if (!started.compareAndSet(false, true)) {
             return;
         }
 
         log.debug("{}: In startTracking", logName());
 
-        this.satisfactionCallback = satisfactionCallback;
+        this.satisfactionCallback = newSatisfactionCallback;
 
         startTracking();
     }
@@ -173,10 +189,47 @@ abstract class AbstractDependentComponentFactoryMetadata implements DependentCom
     }
 
     private void stopServiceRecipes() {
-        for(StaticServiceReferenceRecipe recipe: serviceRecipes) {
+        for (StaticServiceReferenceRecipe recipe: serviceRecipes) {
             recipe.stop();
         }
 
         serviceRecipes.clear();
     }
+
+    protected void restartContainer() {
+        if (restarting.compareAndSet(false, true)) {
+            BlueprintContainerRestartService restartService = getOSGiService(BlueprintContainerRestartService.class);
+            if (restartService != null) {
+                log.debug("{}: Restarting container", logName());
+                restartService.restartContainerAndDependents(container().getBundleContext().getBundle());
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Nullable
+    protected <T> T getOSGiService(Class<T> serviceInterface) {
+        try {
+            ServiceReference<T> serviceReference =
+                    container().getBundleContext().getServiceReference(serviceInterface);
+            if (serviceReference == null) {
+                log.warn("{}: {} reference not found", logName(), serviceInterface.getSimpleName());
+                return null;
+            }
+
+            T service = (T)container().getService(serviceReference);
+            if (service == null) {
+                // This could happen on shutdown if the service was already unregistered so we log as debug.
+                log.debug("{}: {} was not found", logName(), serviceInterface.getSimpleName());
+            }
+
+            return service;
+        } catch (IllegalStateException e) {
+            // This is thrown if the BundleContext is no longer valid which is possible on shutdown so we
+            // log as debug.
+            log.debug("{}: Error obtaining {}", logName(), serviceInterface.getSimpleName(), e);
+        }
+
+        return null;
+    }
 }