You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/04 11:50:47 UTC

[05/45] git commit: osgi wip

osgi wip


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/79ebcc33
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/79ebcc33
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/79ebcc33

Branch: refs/heads/master
Commit: 79ebcc3382cdd3e8725967aa2c139696ce1f2294
Parents: 1809b36
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Jun 10 20:27:57 2014 -0700
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Tue Jul 1 13:37:36 2014 +0100

----------------------------------------------------------------------
 core/pom.xml                                    |   6 +
 .../brooklyn/config/BrooklynServerConfig.java   |   3 +
 .../brooklyn/management/ha/OsgiManager.java     |  48 +++++++
 .../internal/LocalManagementContext.java        |  17 +++
 .../internal/ManagementContextInternal.java     |   5 +
 .../NonDeploymentManagementContext.java         |   6 +
 .../src/main/java/brooklyn/util/osgi/Osgis.java | 139 +++++++++++++++++++
 .../management/osgi/OsgiStandaloneTest.java     | 119 ++++++++++++++++
 .../entity/LocalManagementContextForTests.java  |   9 +-
 .../osgi/brooklyn-osgi-test-a_0.1.0.jar         | Bin 0 -> 2055 bytes
 pom.xml                                         |   1 +
 11 files changed, 351 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 1056ad1..f80aa24 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -85,6 +85,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>${felix.framework.version}</version>
+        </dependency>
+
+        <dependency>
             <groupId>org.reflections</groupId>
             <artifactId>reflections</artifactId>
             <version>${reflections.version}</version>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
index 6154ba6..f564176 100644
--- a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
+++ b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
@@ -131,4 +131,7 @@ public class BrooklynServerConfig {
         "or empty for no URL (use default scanner)", 
         new File(Os.fromHome(".brooklyn/catalog.xml")).toURI().toString());
     
+    public static final ConfigKey<Boolean> USE_OSGI = ConfigKeys.newBooleanConfigKey("brooklyn.osgi.enabled",
+        "Whether OSGi is enabled, defaulting to true", true);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
new file mode 100644
index 0000000..07400ec
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -0,0 +1,48 @@
+package brooklyn.management.ha;
+
+import java.io.File;
+
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.ConfigKey;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+public class OsgiManager {
+
+    public static final ConfigKey<Boolean> USE_OSGI = BrooklynServerConfig.USE_OSGI;
+    
+    /* see Osgis for info on starting framework etc */
+    
+    protected Framework framework;
+    protected File osgiTempDir;
+    
+    public void start() {
+        try {
+            // TODO any extra startup args?
+            // TODO dir to come from brooklyn properties;
+            // note dir must be different for each if starting multiple instances
+            osgiTempDir = Os.newTempDir("brooklyn-osgi-cache");
+            framework = Osgis.newFrameworkStarted(osgiTempDir.getAbsolutePath(), false, MutableMap.of());
+            
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public void stop() {
+        try {
+            if (framework!=null)
+                framework.stop();
+        } catch (BundleException e) {
+            throw Exceptions.propagate(e);
+        }
+        osgiTempDir = Os.deleteRecursively(osgiTempDir).asNullOrThrowing();
+        framework = null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
index c84a200..0d3deb9 100644
--- a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
@@ -34,6 +34,7 @@ import brooklyn.management.ExecutionManager;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.SubscriptionManager;
 import brooklyn.management.Task;
+import brooklyn.management.ha.OsgiManager;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.task.BasicExecutionContext;
 import brooklyn.util.task.BasicExecutionManager;
@@ -99,6 +100,7 @@ public class LocalManagementContext extends AbstractManagementContext {
     private final LocalLocationManager locationManager;
     private final LocalAccessManager accessManager;
     private final LocalUsageManager usageManager;
+    private OsgiManager osgiManager;
     
     public final Throwable constructionStackTrace = new Throwable("for construction stacktrace").fillInStackTrace();
     
@@ -160,6 +162,11 @@ public class LocalManagementContext extends AbstractManagementContext {
         this.accessManager = new LocalAccessManager();
         this.usageManager = new LocalUsageManager(this);
         
+        if (configMap.getConfig(OsgiManager.USE_OSGI)) {
+            this.osgiManager = new OsgiManager();
+            osgiManager.start();
+        }
+        
         INSTANCES.add(this);
         log.debug("Created management context "+this);
     }
@@ -246,6 +253,12 @@ public class LocalManagementContext extends AbstractManagementContext {
         if (!isRunning()) throw new IllegalStateException("Management context no longer running");
         return usageManager;
     }
+    
+    @Override
+    public synchronized OsgiManager getOsgiManager() {
+        if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+        return osgiManager;        
+    }
 
     @Override
     public synchronized AccessController getAccessController() {
@@ -277,6 +290,10 @@ public class LocalManagementContext extends AbstractManagementContext {
     public void terminate() {
         INSTANCES.remove(this);
         super.terminate();
+        if (osgiManager!=null) {
+            osgiManager.stop();
+            osgiManager = null;
+        }
         if (execution != null) execution.shutdownNow();
         if (gc != null) gc.shutdownNow();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
index 2565b40..fb50641 100644
--- a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
+++ b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
@@ -18,6 +18,7 @@ import brooklyn.internal.storage.BrooklynStorage;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
+import brooklyn.management.ha.OsgiManager;
 import brooklyn.util.task.TaskTags;
 
 public interface ManagementContextInternal extends ManagementContext {
@@ -57,6 +58,10 @@ public interface ManagementContextInternal extends ManagementContext {
     AccessManager getAccessManager();
 
     UsageManager getUsageManager();
+    
+    /** returns OSGi manager, if available; may be null if OSGi not supported, e.g. in test contexts
+     * (but major contexts will support this) */
+    OsgiManager getOsgiManager();
 
     InternalEntityFactory getEntityFactory();
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
index 85b7029..61826ef 100644
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -44,6 +44,7 @@ import brooklyn.management.ha.HighAvailabilityMode;
 import brooklyn.management.ha.ManagementNodeState;
 import brooklyn.management.ha.ManagementPlaneSyncRecord;
 import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
+import brooklyn.management.ha.OsgiManager;
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.time.Duration;
@@ -175,6 +176,11 @@ public class NonDeploymentManagementContext implements ManagementContextInternal
     public UsageManager getUsageManager() {
         return usageManager;
     }
+    
+    @Override
+    public OsgiManager getOsgiManager() {
+        return null;
+    }
 
     @Override
     public AccessController getAccessController() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/main/java/brooklyn/util/osgi/Osgis.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/osgi/Osgis.java b/core/src/main/java/brooklyn/util/osgi/Osgis.java
new file mode 100644
index 0000000..2cfc5a7
--- /dev/null
+++ b/core/src/main/java/brooklyn/util/osgi/Osgis.java
@@ -0,0 +1,139 @@
+package brooklyn.util.osgi;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.framework.FrameworkFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.launch.Framework;
+
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+/** 
+ * utilities for working with osgi.
+ * osgi support is in early days (June 2014) so this class is beta, subject to change,
+ * particularly in how framework is started and bundles installed.
+ * 
+ * @since 0.7.0  */
+@Beta
+public class Osgis {
+
+    public static List<Bundle> getBundlesByName(Framework framework, String symbolicName, Predicate<Version> versionMatcher) {
+        List<Bundle> result = MutableList.of();
+        for (Bundle b: framework.getBundleContext().getBundles()) {
+            if (symbolicName.equals(b.getSymbolicName())) {
+                if (versionMatcher.apply(b.getVersion())) {
+                    result.add(b);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static List<Bundle> getBundlesByName(Framework framework, String symbolicName) {
+        return getBundlesByName(framework, symbolicName, Predicates.<Version>alwaysTrue());
+    }
+    
+    public static Maybe<Bundle> getBundle(Framework framework, String symbolicNameOptionallyWithVersion) {
+        String[] parts = symbolicNameOptionallyWithVersion.split(":");
+        List<Bundle> matches;
+        if (parts.length==2) {
+            return getBundle(framework, symbolicNameOptionallyWithVersion);
+        } else if (parts.length==1) {
+            matches = getBundlesByName(framework, symbolicNameOptionallyWithVersion);
+            if (matches.isEmpty()) return Maybe.absent("no bundles matching "+symbolicNameOptionallyWithVersion);
+            return Maybe.of(matches.iterator().next());
+        } else {
+            throw new IllegalArgumentException("Cannot parse symbolic-name:version string '"+symbolicNameOptionallyWithVersion+"'");
+        }
+    }
+    
+    public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, String version) {
+        return getBundle(framework, symbolicName, Version.parseVersion(version));
+    }
+
+    public static Maybe<Bundle> getBundle(Framework framework, String symbolicName, Version version) {
+        List<Bundle> matches = getBundlesByName(framework, symbolicName, Predicates.<Version>equalTo(version));
+        if (matches.isEmpty()) return Maybe.absent("no bundles matching "+symbolicName+":"+version);
+        return Maybe.of(matches.iterator().next());
+    }
+
+    // -------- creating
+    
+    /*
+     * loading framework factory and starting framework based on:
+     * http://felix.apache.org/documentation/subprojects/apache-felix-framework/apache-felix-framework-launching-and-embedding.html :
+     */
+    
+    public static FrameworkFactory newFrameworkFactory() {
+        URL url = Osgis.class.getClassLoader().getResource(
+                "META-INF/services/org.osgi.framework.launch.FrameworkFactory");
+        if (url != null) {
+            try {
+                BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
+                try {
+                    for (String s = br.readLine(); s != null; s = br.readLine()) {
+                        s = s.trim();
+                        // load the first non-empty, non-commented line
+                        if ((s.length() > 0) && (s.charAt(0) != '#')) {
+                            return (FrameworkFactory) Class.forName(s).newInstance();
+                        }
+                    }
+                } finally {
+                    if (br != null) br.close();
+                }
+            } catch (Exception e) {
+                // class creation exceptions are not interesting to caller...
+                throw Exceptions.propagate(e);
+            }
+        }
+        throw new IllegalStateException("Could not find framework factory.");
+    }
+    
+    public static Framework newFrameworkStarted(String felixCacheDir, boolean clean, Map<?,?> extraStartupConfig) {
+        Map<Object,Object> cfg = MutableMap.copyOf(extraStartupConfig);
+        if (clean) cfg.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
+        if (felixCacheDir!=null) cfg.put(Constants.FRAMEWORK_STORAGE, felixCacheDir);
+        FrameworkFactory factory = newFrameworkFactory();
+        
+        Framework framework = factory.newFramework(cfg);
+        try {
+            framework.init();
+            // nothing needs auto-loading, currently (and this needs a new dependency)
+//            AutoProcessor.process(configProps, m_fwk.getBundleContext());
+            framework.start();
+        } catch (Exception e) {
+            // framework bundle start exceptions are not interesting to caller...
+            throw Exceptions.propagate(e);
+        }
+        return framework;
+    }
+
+    /** install a bundle from the given URL, doing a check if already installed, and
+     * using the {@link ResourceUtils} loader for this project (brooklyn core) */
+    public static Bundle install(Framework framework, String url) throws BundleException {
+        Bundle bundle = framework.getBundleContext().getBundle(url);
+        if (bundle!=null) return bundle;
+        
+        // use our URL resolution so we get classpath items
+        InputStream stream = ResourceUtils.create(Osgis.class).getResourceFromUrl(url);
+        return framework.getBundleContext().installBundle(url, stream);
+    }
+    
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
new file mode 100644
index 0000000..7ffaf2d
--- /dev/null
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
@@ -0,0 +1,119 @@
+package brooklyn.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+/** tests some assumptions about OSGi behaviour, in standalone mode (not part of brooklyn).
+ * 
+ * relies on the following bundles, which exist in the classpath (and contain their sources):
+ * 
+ * <li>brooklyn-osgi-test-a_0.1.0 -
+ *     defines TestA which has a "times" method and a static multiplier field;
+ *     we set the multiplier to determine when we are sharing versions and when not
+ *     
+ *  */
+public class OsgiStandaloneTest {
+
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:///brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
+    
+    protected Framework framework = null;
+    private File storageTempDir;
+
+    @BeforeMethod
+    public void setUp() throws Exception {
+        storageTempDir = Os.newTempDir("osgi-standalone");
+        framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
+    }
+
+    @AfterMethod
+    public void tearDown() throws BundleException, IOException {
+        if (framework!=null) {
+            framework.stop();
+            framework = null;
+        }
+        if (storageTempDir!=null) {
+            FileUtils.deleteDirectory(storageTempDir);
+            storageTempDir = null;
+        }
+    }
+
+    protected Bundle install(String url) throws BundleException {
+        try {
+            return Osgis.install(framework, url);
+        } catch (Exception e) {
+            throw new IllegalStateException("test resources not available; may be an IDE issue, so try a mvn rebuild of this project", e);
+        }
+    }
+    
+    @Test
+    public void testInstallBundle() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+    }
+
+    @Test
+    public void testAMultiplier() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+        setAMultiplier(bundle, 5);
+        checkMath(bundle, 3, 15);
+    }
+
+    /** run two multiplier tests to ensure that irrespective of order the tests run in, 
+     * on a fresh install the multiplier is reset */
+    @Test
+    public void testANOtherMultiple() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+        setAMultiplier(bundle, 14);
+        checkMath(bundle, 3, 42);
+    }
+
+    @Test
+    public void testGetBundle() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        setAMultiplier(bundle, 3);
+
+        // can look it up based on the same location string (no other "location identifier" reference string seems to work here, however) 
+        Bundle bundle2 = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle2, 3, 9);
+    }
+
+    @Test
+    public void testUninstallAndReinstallBundle() throws Exception {
+        Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle, 3, 6);
+        setAMultiplier(bundle, 3);
+        checkMath(bundle, 3, 9);
+        bundle.uninstall();
+        
+        Bundle bundle2 = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);
+        checkMath(bundle2, 3, 6);
+    }
+
+    protected void checkMath(Bundle bundle, int input, int output) throws Exception {
+        Assert.assertNotNull(bundle);
+        Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
+        Object aInst = aClass.newInstance();
+        Object result = aClass.getMethod("times", int.class).invoke(aInst, input);
+        Assert.assertEquals(result, output);
+    }
+    protected void setAMultiplier(Bundle bundle, int newMultiplier) throws Exception {
+        Assert.assertNotNull(bundle);
+        Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
+        aClass.getField("multiplier").set(null, newMultiplier);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java b/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
index 2b2a884..3631ff4 100644
--- a/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
+++ b/core/src/test/java/brooklyn/test/entity/LocalManagementContextForTests.java
@@ -2,7 +2,6 @@ package brooklyn.test.entity;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.BrooklynServerConfig;
-import brooklyn.management.internal.AbstractManagementContext;
 import brooklyn.management.internal.LocalManagementContext;
 
 /** management context which forces an empty catalog to prevent scanning / interacting with local filesystem.
@@ -21,7 +20,13 @@ public class LocalManagementContextForTests extends LocalManagementContext {
 
     public static BrooklynProperties setEmptyCatalogAsDefault(BrooklynProperties brooklynProperties) {
         if (brooklynProperties==null) return null;
-        brooklynProperties.putIfAbsent(AbstractManagementContext.BROOKLYN_CATALOG_URL, "classpath://brooklyn-catalog-empty.xml");
+        brooklynProperties.putIfAbsent(BrooklynServerConfig.BROOKLYN_CATALOG_URL, "classpath://brooklyn-catalog-empty.xml");
+        return brooklynProperties;
+    }
+    
+    public static BrooklynProperties disableOsgi(BrooklynProperties brooklynProperties) {
+        if (brooklynProperties==null) return null;
+        brooklynProperties.putIfAbsent(BrooklynServerConfig.USE_OSGI, false);
         return brooklynProperties;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar
new file mode 100644
index 0000000..b4c777c
Binary files /dev/null and b/core/src/test/resources/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/79ebcc33/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f95beca..70a128b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
         <mx4j.version>3.0.1</mx4j.version>
         <bouncycastle.version>1.49</bouncycastle.version>
         <sshj.version>0.8.1</sshj.version>
+        <felix.framework.version>4.4.0</felix.framework.version>
         <reflections.version>0.9.9-RC1</reflections.version>
         <jetty.version>8.1.4.v20120524</jetty.version>
         <airline.version>0.6</airline.version>