Applied patch FELIX-3379 to separate launcher and not use Felix-specific API.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1298472 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/examples/extenderbased.host/pom.xml b/examples/extenderbased.host/pom.xml
index aff58b2..6cf6f2c 100644
--- a/examples/extenderbased.host/pom.xml
+++ b/examples/extenderbased.host/pom.xml
@@ -49,7 +49,7 @@
<configuration>
<instructions>
<_donotcopy>(CVS|.svn|config.properties)</_donotcopy>
- <Main-Class>org.apache.felix.example.extenderbased.host.Activator</Main-Class>
+ <Main-Class>org.apache.felix.example.extenderbased.host.launch.Application</Main-Class>
<Import-Package>!android.*,!dalvik.*,org.osgi.framework,org.osgi.service.packageadmin,org.osgi.service.url,org.osgi.service.startlevel,org.osgi.util.tracker,*</Import-Package>
<Export-Package>org.apache.felix.example.extenderbased.host.extension.*</Export-Package>
<Private-Package>org.apache.felix.example.extenderbased.host.*</Private-Package>
@@ -63,8 +63,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>1.5</source>
- <target>1.5</target>
+ <source>1.6</source>
+ <target>1.6</target>
</configuration>
</plugin>
</plugins>
diff --git a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/Activator.java b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/Activator.java
index c2ad46d..7f6a8ca 100644
--- a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/Activator.java
+++ b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/Activator.java
@@ -20,20 +20,13 @@
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
-import org.apache.felix.framework.Felix;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.main.AutoActivator;
+
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
/**
* The activator of the host application bundle. The activator creates the
@@ -42,13 +35,6 @@
* synchronization and repainting issues. Closing the application window
* will result in <tt>Bundle.stop()</tt> being called on the system bundle,
* which will cause the framework to shutdown and the JVM to exit.
- * <p>
- * This class also provides a static <tt>main()</tt> method so that it can be
- * run as a stand-alone host application. In such a scenario, the application
- * creates its own embedded Felix framework instance and interacts with the
- * internal extensions to providing drawing functionality. To successfully
- * launch the stand-alone application, it must be run from this bundle's
- * installation directory using "<tt>java -jar</tt>".
**/
public class Activator implements BundleActivator
{
@@ -61,10 +47,12 @@
* and repainting issues.
* @param context The context of the bundle.
**/
+ @Override
public void start(final BundleContext context)
{
SwingUtilities.invokeLater(new Runnable() {
// This creates of the application window.
+ @Override
public void run()
{
m_frame = new DrawingFrame();
@@ -97,10 +85,12 @@
* Stops extension tracking and disposes of the application window.
* @param context The context of the bundle.
**/
+ @Override
public void stop(BundleContext context)
{
Runnable runner = new Runnable() {
// This disposes of the application window.
+ @Override
public void run()
{
m_shapetracker.close();
@@ -125,79 +115,4 @@
}
}
}
-
- /**
- * Enables the bundle to run as a stand-alone application. When this
- * static <tt>main()</tt> method is invoked, the application creates
- * its own embedded Felix framework instance and interacts with the
- * internal extensions to provide drawing functionality. To successfully
- * launch as a stand-alone application, this method should be invoked from
- * the bundle's installation directory using "<tt>java -jar</tt>".
- * @param argv The command-line arguments.
- * @throws Exception If anything goes wrong.
- **/
- public static void main(String[] argv) throws Exception
- {
- // Create a temporary bundle cache directory and
- // make sure to clean it up on exit.
- final File cachedir = File.createTempFile("felix.example.extenderbased", null);
- cachedir.delete();
- Runtime.getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run()
- {
- deleteFileOrDir(cachedir);
- }
- });
-
- Map<String, Object> configMap = new HashMap<String, Object>();
- configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
- "org.apache.felix.example.extenderbased.host.extension; version=1.0.0");
- configMap.put(AutoActivator.AUTO_START_PROP + ".1",
- "file:../extenderbased.circle/target/extenderbased.circle-1.0.0.jar " +
- "file:../extenderbased.square/target/extenderbased.square-1.0.0.jar " +
- "file:../extenderbased.triangle/target/extenderbased.triangle-1.0.0.jar");
- configMap.put(FelixConstants.LOG_LEVEL_PROP, "4");
- configMap.put(Constants.FRAMEWORK_STORAGE, cachedir.getAbsolutePath());
-
- // Create list to hold custom framework activators.
- List<BundleActivator> list = new ArrayList<BundleActivator>();
- // Add activator to process auto-start/install properties.
- list.add(new AutoActivator(configMap));
- // Add our own activator.
- list.add(new Activator());
- // Add our custom framework activators to the configuration map.
- configMap.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
-
- try
- {
- // Now create an instance of the framework.
- Felix felix = new Felix(configMap);
- felix.start();
- }
- catch (Exception ex)
- {
- System.err.println("Could not create framework: " + ex);
- ex.printStackTrace();
- System.exit(-1);
- }
- }
-
- /**
- * Utility method used to delete the profile directory when run as
- * a stand-alone application.
- * @param file The file to recursively delete.
- **/
- private static void deleteFileOrDir(File file)
- {
- if (file.isDirectory())
- {
- File[] childs = file.listFiles();
- for (int i = 0;i < childs.length;i++)
- {
- deleteFileOrDir(childs[i]);
- }
- }
- file.delete();
- }
}
\ No newline at end of file
diff --git a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/launch/Application.java b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/launch/Application.java
new file mode 100644
index 0000000..2f5516e
--- /dev/null
+++ b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/launch/Application.java
@@ -0,0 +1,128 @@
+/*
+ * 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.example.extenderbased.host.launch;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.apache.felix.example.extenderbased.host.Activator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+/**
+ * This class provides a static {@code main()} method so that the bundle can be
+ * run as a stand-alone host application. In such a scenario, the application
+ * creates its own embedded OSGi framework instance and interacts with the
+ * internal extensions to providing drawing functionality. To successfully
+ * launch the stand-alone application, it must be run from this bundle's
+ * installation directory using "{@code java -jar}".
+ * The locations of any additional extensions that have to be started, have to
+ * be passed as command line arguments to this method.
+ */
+public class Application
+{
+ private static Framework m_framework = null;
+
+ /**
+ * Enables the bundle to run as a stand-alone application. When this
+ * static {@code main()} method is invoked, the application creates
+ * its own embedded OSGi framework instance and interacts with the
+ * internal extensions to provide drawing functionality. To successfully
+ * launch as a stand-alone application, this method should be invoked from
+ * the bundle's installation directory using "{@code java -jar}".
+ * The location of any extension that shall be installed can be passed
+ * as parameters.
+ * <p>
+ * For example if you build the bundles inside your workspace, maven will
+ * create a target directory in every project. To start the application
+ * from within your IDE you should pass:
+ * <p>
+ * <pre>
+ * {@code file:../extenderbased.circle/target/extenderbased.circle-1.0.0.jar
+ * file:../extenderbased.square/target/extenderbased.square-1.0.0.jar
+ * file:../extenderbased.triangle/target/extenderbased.triangle-1.0.0.jar}
+ * </pre>
+ *
+ * @param args The locations of additional bundles to start.
+ **/
+ public static void main(String[] args)
+ {
+ // args should never be null if the application is run from the command line. Check it anyway.
+ String[] locations = args != null ? args : new String[0];
+
+ // Print welcome banner.
+ System.out.println("\nWelcome to My Launcher");
+ System.out.println("======================\n");
+
+ try
+ {
+ Map<String, Object> config = ConfigUtil.createConfig();
+ m_framework = createFramework(config);
+ m_framework.init();
+ m_framework.start();
+ installAndStartBundles(locations);
+ m_framework.waitForStop(0);
+ System.exit(0);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Could not create framework: " + ex);
+ ex.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Util method for creating an embedded Framework. Tries to create a {@link FrameworkFactory}
+ * which is then be used to create the framework.
+ *
+ * @param config the configuration to create the framework with
+ * @return a Framework with the given configuration
+ */
+ private static Framework createFramework(Map<String, Object> config)
+ {
+ ServiceLoader<FrameworkFactory> factoryLoader = ServiceLoader.load(FrameworkFactory.class);
+ for(FrameworkFactory factory : factoryLoader){
+ return factory.newFramework(config);
+ }
+ throw new IllegalStateException("Unable to load FrameworkFactory service.");
+ }
+
+ /**
+ * Installs and starts all bundles used by the application. Therefore the host bundle will be started. The locations
+ * of extensions for the host bundle can be passed in as parameters.
+ *
+ * @param bundleLocations the locations where extension for the host bundle are located. Must not be {@code null}!
+ * @throws BundleException if something went wrong while installing or starting the bundles.
+ */
+ private static void installAndStartBundles(String... bundleLocations) throws BundleException
+ {
+ BundleContext bundleContext = m_framework.getBundleContext();
+ Activator hostActivator = new Activator();
+ hostActivator.start(bundleContext);
+ for (String location : bundleLocations)
+ {
+ Bundle addition = bundleContext.installBundle(location);
+ addition.start();
+ }
+ }
+}
diff --git a/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/launch/ConfigUtil.java b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/launch/ConfigUtil.java
new file mode 100644
index 0000000..b4375f6
--- /dev/null
+++ b/examples/extenderbased.host/src/main/java/org/apache/felix/example/extenderbased/host/launch/ConfigUtil.java
@@ -0,0 +1,116 @@
+/*
+ * 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.example.extenderbased.host.launch;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+
+/**
+ * Util class for creating the framework configuration
+ */
+final class ConfigUtil
+{
+
+ /**
+ * Creates a configuration for the framework. Therefore this method attempts to create
+ * a temporary cache dir. If creation of the cache dir is successful, it will be added
+ * to the configuration.
+ *
+ * @return
+ */
+ public static Map<String, Object> createConfig()
+ {
+ final File cachedir = createCacheDir();
+
+ Map<String, Object> configMap = new HashMap<String, Object>();
+ // Tells the framework to export the extension package, making it accessible for the other shape bundels
+ configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
+ "org.apache.felix.example.extenderbased.host.extension; version=1.0.0");
+
+ // if we could create a cache dir, we use it. Otherwise the platform default will be used
+ if (cachedir != null)
+ {
+ configMap.put(Constants.FRAMEWORK_STORAGE, cachedir.getAbsolutePath());
+ }
+
+ return configMap;
+ }
+
+ /**
+ * Tries to create a temporay cache dir. If creation of the cache dir is successful,
+ * it will be returned. If creation fails, null will be returned.
+ *
+ * @return a {@code File} object representing the cache dir
+ */
+ private static File createCacheDir()
+ {
+ final File cachedir;
+ try
+ {
+ cachedir = File.createTempFile("felix.example.extenderbased", null);
+ cachedir.delete();
+ createShutdownHook(cachedir);
+ return cachedir;
+ }
+ catch (IOException e)
+ {
+ // temp dir creation failed, return null
+ return null;
+ }
+ }
+
+ /**
+ * Adds a shutdown hook to the runtime, that will make sure, that the cache dir will
+ * be deleted after the application has been terminated.
+ */
+ private static void createShutdownHook(final File cachedir)
+ {
+ Runtime.getRuntime().addShutdownHook(new Thread()
+ {
+ @Override
+ public void run()
+ {
+ deleteFileOrDir(cachedir);
+ }
+ });
+ }
+
+
+ /**
+ * Utility method used to delete the profile directory when run as
+ * a stand-alone application.
+ * @param file The file to recursively delete.
+ **/
+ private static void deleteFileOrDir(File file)
+ {
+ if (file.isDirectory())
+ {
+ File[] childs = file.listFiles();
+ for (File child : childs)
+ {
+ deleteFileOrDir(child);
+ }
+ }
+ file.delete();
+ }
+}