FELIX-4579 Support Framework Extension Bundle Activators
Unit test included.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1640381 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index 2fab5fa..a76a769 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -19,14 +19,15 @@
package org.apache.felix.framework;
import java.io.IOException;
-import java.net.InetAddress;
import java.io.InputStream;
+import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.security.AllPermission;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,12 +37,13 @@
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
+
+import org.apache.felix.framework.cache.Content;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.ImmutableList;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.framework.cache.Content;
import org.apache.felix.framework.util.manifestparser.R4Library;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
@@ -249,30 +251,30 @@
String osVersion = (String)m_configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
String userLang = (String)m_configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
Map<String, Object> attributes = new HashMap<String, Object>();
-
- if( osArchitecture != null )
+
+ if( osArchitecture != null )
{
attributes.put(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, osArchitecture);
}
-
+
if( osName != null)
{
attributes.put(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, osName);
}
-
+
if( osVersion != null)
{
attributes.put(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, new Version(osVersion));
}
-
- if( userLang != null)
+
+ if( userLang != null)
{
attributes.put(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, userLang);
}
-
+
return new BundleCapabilityImpl(getRevision(), NativeNamespace.NATIVE_NAMESPACE, Collections.<String, String> emptyMap(), attributes);
}
-
+
private static List<BundleCapability> aliasSymbolicName(List<BundleCapability> caps)
{
if (caps == null)
@@ -463,9 +465,10 @@
*/
void startExtensionBundle(Felix felix, BundleImpl bundle)
{
- String activatorClass = (String)
- ((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
- .getHeaders().get(FelixConstants.FELIX_EXTENSION_ACTIVATOR);
+ Dictionary<?,?> headers = bundle.getHeaders();
+ String activatorClass = (String) headers.get(Constants.EXTENSION_BUNDLE_ACTIVATOR);
+ if (activatorClass == null)
+ activatorClass = (String) headers.get(FelixConstants.FELIX_EXTENSION_ACTIVATOR);
if (activatorClass != null)
{
@@ -491,7 +494,7 @@
catch (Throwable ex)
{
m_logger.log(bundle, Logger.LOG_WARNING,
- "Unable to start Felix Extension Activator", ex);
+ "Unable to start Extension Activator", ex);
}
}
}
diff --git a/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java b/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
index 3201625..63e4a79 100644
--- a/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
@@ -1,81 +1,189 @@
-/*
- * 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.felix.framework;
-
-import static org.junit.Assert.*;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.felix.framework.util.FelixConstants;
-import org.junit.Test;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.NativeNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-
-/**
- *
- * Test Classes for the ExtentionManager
- *
- */
-public class ExtensionManagerTest {
-
- /**
- *
- *
- * Ensure Native Bundle Capabilities are properly formed based on
- * Framework properties.
- *
- */
- @Test
- public void testBuildNativeCapabilities() {
- Logger logger = new Logger();
- Map<String, String> configMap = new HashMap<String, String>();
- configMap.put(FelixConstants.FELIX_VERSION_PROPERTY, "1.0");
- configMap.put(FelixConstants.FRAMEWORK_LANGUAGE, "en");
- configMap.put(FelixConstants.FRAMEWORK_PROCESSOR, "x86_64");
- configMap.put(FelixConstants.FRAMEWORK_OS_NAME, "windows8");
- configMap.put(FelixConstants.FRAMEWORK_OS_VERSION, "6.3");
- ExtensionManager extensionManager = new ExtensionManager(logger,
- configMap, null);
- BundleCapability nativeBundleCapability = extensionManager
- .buildNativeCapabilites();
- assertEquals(
- "Native Language should be same as framework Language",
- "en",
- nativeBundleCapability.getAttributes().get(
- NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE));
- assertEquals(
- "Native Processor should be same as framework Processor",
- "x86_64",
- nativeBundleCapability.getAttributes().get(
- NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE));
- assertEquals(
- "Native OS Name should be the same as the framework os name",
- "windows8",
- nativeBundleCapability.getAttributes().get(
- NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE));
- assertEquals(
- "Native OS Version should be the same as the framework OS Version",
- new Version("6.3"),
- nativeBundleCapability.getAttributes().get(
- NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE));
- }
-
-}
+/*
+ * 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.felix.framework;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+import org.apache.felix.framework.util.FelixConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.NativeNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+
+/**
+ *
+ * Test Classes for the ExtentionManager
+ *
+ */
+public class ExtensionManagerTest {
+ private int counter;
+ private File testDir;
+
+ @Before
+ public void setUp() throws Exception {
+ String path = "/" + getClass().getName().replace('.', '/') + ".class";
+ String url = getClass().getResource(path).getFile();
+ String baseDir = url.substring(0, url.length() - path.length());
+ String rndStr = Long.toString(System.nanoTime(), Character.MAX_RADIX);
+ rndStr = rndStr.substring(rndStr.length() - 6, rndStr.length() - 1);
+ testDir = new File(baseDir, getClass().getSimpleName() + "_" + rndStr);
+ }
+
+ /**
+ *
+ *
+ * Ensure Native Bundle Capabilities are properly formed based on
+ * Framework properties.
+ *
+ */
+ @Test
+ public void testBuildNativeCapabilities() {
+ Logger logger = new Logger();
+ Map<String, String> configMap = new HashMap<String, String>();
+ configMap.put(FelixConstants.FELIX_VERSION_PROPERTY, "1.0");
+ configMap.put(FelixConstants.FRAMEWORK_LANGUAGE, "en");
+ configMap.put(FelixConstants.FRAMEWORK_PROCESSOR, "x86_64");
+ configMap.put(FelixConstants.FRAMEWORK_OS_NAME, "windows8");
+ configMap.put(FelixConstants.FRAMEWORK_OS_VERSION, "6.3");
+ ExtensionManager extensionManager = new ExtensionManager(logger,
+ configMap, null);
+ BundleCapability nativeBundleCapability = extensionManager
+ .buildNativeCapabilites();
+ assertEquals(
+ "Native Language should be same as framework Language",
+ "en",
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE));
+ assertEquals(
+ "Native Processor should be same as framework Processor",
+ "x86_64",
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE));
+ assertEquals(
+ "Native OS Name should be the same as the framework os name",
+ "windows8",
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE));
+ assertEquals(
+ "Native OS Version should be the same as the framework OS Version",
+ new Version("6.3"),
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE));
+ }
+
+ @Test
+ public void testExtensionBundleActivator() throws Exception {
+ File cacheDir = new File(testDir, "cache");
+ cacheDir.mkdirs();
+ String cache = cacheDir.getAbsolutePath();
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("felix.cache.profiledir", cache);
+ params.put("felix.cache.dir", cache);
+ params.put(Constants.FRAMEWORK_STORAGE, cache);
+
+ Framework framework = new Felix(params);
+ framework.init();
+ framework.start();
+
+ try {
+ File ebf = createExtensionBundle();
+
+ assertEquals("Precondition", 0, activatorCalls.length());
+ framework.getBundleContext().installBundle(
+ ebf.toURI().toURL().toExternalForm());
+
+ assertEquals("start", activatorCalls.toString());
+ } finally {
+ framework.stop();
+ }
+
+ framework.waitForStop(10000);
+ assertEquals("startstop", activatorCalls.toString());
+ }
+
+ private File createExtensionBundle() throws IOException {
+ File f = File.createTempFile("felix-bundle" + counter++, ".jar", testDir);
+
+ Manifest mf = new Manifest();
+ mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, "extension-bundle");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, "3.2.1");
+ mf.getMainAttributes().putValue(Constants.FRAGMENT_HOST, "system.bundle;extension:=framework");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
+ mf.getMainAttributes().putValue(Constants.EXTENSION_BUNDLE_ACTIVATOR, TestActivator.class.getName());
+ JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
+
+ String path = TestActivator.class.getName().replace('.', '/') + ".class";
+ os.putNextEntry(new ZipEntry(path));
+
+ InputStream is = TestActivator.class.getClassLoader().getResourceAsStream(path);
+ pumpStreams(is, os);
+
+ is.close();
+ os.close();
+ return f;
+ }
+
+ static void pumpStreams(InputStream is, OutputStream os) throws IOException {
+ byte[] bytes = new byte[16384];
+
+ int length = 0;
+ int offset = 0;
+
+ while ((length = is.read(bytes, offset, bytes.length - offset)) != -1) {
+ offset += length;
+
+ if (offset == bytes.length) {
+ os.write(bytes, 0, bytes.length);
+ offset = 0;
+ }
+ }
+ if (offset != 0) {
+ os.write(bytes, 0, offset);
+ }
+ }
+
+ private static StringBuilder activatorCalls = new StringBuilder();
+ public static class TestActivator implements BundleActivator {
+ public void start(BundleContext context) throws Exception {
+ activatorCalls.append("start");
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ activatorCalls.append("stop");
+ }
+ }
+}