Add Blueprint bundle tracker 48/35848/15
authorTom Pantelis <tpanteli@brocade.com>
Tue, 5 Apr 2016 04:30:37 +0000 (00:30 -0400)
committerAnil Vishnoi <vishnoianil@gmail.com>
Thu, 7 Apr 2016 18:08:38 +0000 (18:08 +0000)
Added an initial blueprint bundle and BlueprintBundleTracker which
scans ACTIVE bundles for blueprint XML files located under the well-known
org/opendaylight/blueprint/ path and deploys the XML files via the
Aries BlueprintExtenderService. This path differs from the standard
OSGI-INF/blueprint path to allow for controlled deployment of
blueprint containers in an orderly manner.

Change-Id: I21fd5aeb1d9ccd609caa8ea89bd66648fee5ad97
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/blueprint/pom.xml [new file with mode: 0644]
opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java [new file with mode: 0644]
pom.xml

diff --git a/opendaylight/blueprint/pom.xml b/opendaylight/blueprint/pom.xml
new file mode 100644 (file)
index 0000000..511a185
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.7.0-SNAPSHOT</version>
+    <relativePath>../commons/opendaylight</relativePath>
+  </parent>
+
+  <artifactId>blueprint</artifactId>
+  <packaging>bundle</packaging>
+  <name>${project.artifactId}</name>
+  <version>0.5.0-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.aries.blueprint</groupId>
+      <artifactId>org.apache.aries.blueprint.core</artifactId>
+      <version>1.4.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Bundle-Activator>org.opendaylight.controller.blueprint.BlueprintBundleTracker</Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java
new file mode 100644 (file)
index 0000000..98e31e8
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.blueprint;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import org.apache.aries.blueprint.services.BlueprintExtenderService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.blueprint.container.EventConstants;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is created in bundle activation and scans ACTIVE bundles for blueprint XML files located under
+ * the well-known org/opendaylight/blueprint/ path and deploys the XML files via the Aries
+ * BlueprintExtenderService. This path differs from the standard OSGI-INF/blueprint path to allow for
+ * controlled deployment of blueprint containers in an orderly manner.
+ *
+ * @author Thomas Pantelis
+ */
+public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCustomizer<Bundle>, EventHandler {
+    private static final Logger LOG = LoggerFactory.getLogger(BlueprintBundleTracker.class);
+    private static final String BLUEPRINT_FILE_PATH = "org/opendaylight/blueprint/";
+    private static final String BLUEPRINT_FLE_PATTERN = "*.xml";
+
+    private ServiceTracker<BlueprintExtenderService, BlueprintExtenderService> serviceTracker;
+    private BundleTracker<Bundle> bundleTracker;
+    private volatile BlueprintExtenderService blueprintExtenderService;
+    private ServiceRegistration<?> eventHandlerReg;
+
+    /**
+     * Implemented from BundleActivator.
+     */
+    @Override
+    public void start(BundleContext context) {
+        LOG.info("Starting {}", getClass().getSimpleName());
+
+        // Register EventHandler for blueprint events
+
+        Dictionary<String, Object> props = new Hashtable<>();
+        props.put(org.osgi.service.event.EventConstants.EVENT_TOPIC, EventConstants.TOPIC_CREATED);
+        eventHandlerReg = context.registerService(EventHandler.class.getName(), this, props);
+
+        bundleTracker = new BundleTracker<>(context, Bundle.ACTIVE, this);
+
+        serviceTracker = new ServiceTracker<>(context, BlueprintExtenderService.class.getName(),
+                new ServiceTrackerCustomizer<BlueprintExtenderService, BlueprintExtenderService>() {
+                    @Override
+                    public BlueprintExtenderService addingService(
+                            ServiceReference<BlueprintExtenderService> reference) {
+                        blueprintExtenderService = reference.getBundle().getBundleContext().getService(reference);
+                        bundleTracker.open();
+
+                        LOG.debug("Got BlueprintExtenderService");
+
+                        return blueprintExtenderService;
+                    }
+
+                    @Override
+                    public void modifiedService(ServiceReference<BlueprintExtenderService> reference,
+                            BlueprintExtenderService service) {
+                    }
+
+                    @Override
+                    public void removedService(ServiceReference<BlueprintExtenderService> reference,
+                            BlueprintExtenderService service) {
+                    }
+                });
+        serviceTracker.open();
+    }
+
+    /**
+     * Implemented from BundleActivator.
+     */
+    @Override
+    public void stop(BundleContext context) {
+        bundleTracker.close();
+        serviceTracker.close();
+        eventHandlerReg.unregister();
+    }
+
+    /**
+     * Implemented from BundleActivator.
+     */
+    @Override
+    public Bundle addingBundle(Bundle bundle, BundleEvent event) {
+        modifiedBundle(bundle, event, bundle);
+        return bundle;
+    }
+
+    /**
+     * Implemented from BundleActivator.
+     */
+    @Override
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Bundle object) {
+        if(bundle.getState() == Bundle.ACTIVE) {
+            List<Object> paths = findBlueprintPaths(bundle);
+
+            if(!paths.isEmpty()) {
+                LOG.info("Creating blueprint container for bundle {} with paths {}", bundle, paths);
+
+                blueprintExtenderService.createContainer(bundle, paths);
+            }
+        }
+    }
+
+    /**
+     * Implemented from BundleActivator.
+     */
+    @Override
+    public void removedBundle(Bundle bundle, BundleEvent event, Bundle object) {
+        // BlueprintExtenderService will handle this.
+    }
+
+    /**
+     * Implemented from EventHandler to listen for blueprint events.
+     *
+     * @param event
+     */
+    @Override
+    public void handleEvent(Event event) {
+        if(EventConstants.TOPIC_CREATED.equals(event.getTopic())) {
+            LOG.info("Blueprint container for bundle {} was successfully created",
+                    event.getProperty(EventConstants.BUNDLE));
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    static List<Object> findBlueprintPaths(Bundle bundle) {
+        Enumeration<?> e = bundle.findEntries(BLUEPRINT_FILE_PATH, BLUEPRINT_FLE_PATTERN, false);
+        if(e == null) {
+            return Collections.emptyList();
+        } else {
+            return Collections.list((Enumeration)e);
+        }
+    }
+}
diff --git a/pom.xml b/pom.xml
index c082be41b60bd7de5f114495a1e0673844a075d5..28757fd255bf8c064e59ea94739e8566ad9e279e 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,8 @@
 
     <module>opendaylight/model</module>
 
+    <module>opendaylight/blueprint</module>
+
     <!-- Parents -->
     <module>opendaylight/commons/protocol-framework</module>
     <module>opendaylight/commons/checkstyle</module>