Repository: incubator-taverna-osgi
Updated Branches:
  refs/heads/master 331066d6a -> 88f732299


osgi-launcher -> taverna-osgi-launcher


Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/commit/de79bd3c
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/tree/de79bd3c
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/diff/de79bd3c

Branch: refs/heads/master
Commit: de79bd3ce2ccec89da1567503e9022fdff2343a8
Parents: 331066d
Author: Stian Soiland-Reyes <[email protected]>
Authored: Mon Feb 15 16:02:14 2016 +0000
Committer: Stian Soiland-Reyes <[email protected]>
Committed: Mon Feb 15 16:02:14 2016 +0000

----------------------------------------------------------------------
 README.md                                       |   2 +-
 osgi-launcher/pom.xml                           |  36 --
 .../taverna/osgilauncher/OsgiLauncher.java      | 430 -------------------
 pom.xml                                         |   2 +-
 taverna-osgi-launcher/pom.xml                   |  36 ++
 .../taverna/osgilauncher/OsgiLauncher.java      | 430 +++++++++++++++++++
 6 files changed, 468 insertions(+), 468 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/de79bd3c/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 9aa2698..e2cd972 100644
--- a/README.md
+++ b/README.md
@@ -123,7 +123,7 @@ contain the corresponding implementation(s).
 * [taverna-plugin-impl](taverna-plugin-impl/) - Apache Taverna Plugin 
implementation
 * [taverna-update-api](taverna-update-api/) - Apache Taverna Update API
 * [taverna-update-impl](taverna-update-impl/) - Apache Taverna Update 
implementation
-* [osgi-launcher](osgi-launcher/) - Apache Taverna OSGi Framework Launcher
+* [taverna-osgi-launcher](taverna-osgi-launcher/) - Apache Taverna OSGi 
Framework Launcher
 * [xml-parser-service](xml-parser-service/) - Apache Taverna XML Parser 
Service for OSGi
 * [xml-transformer-service](xml-transformer-service/) - Apache Taverna XML 
Transformer Service for OSGi
 

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/de79bd3c/osgi-launcher/pom.xml
----------------------------------------------------------------------
diff --git a/osgi-launcher/pom.xml b/osgi-launcher/pom.xml
deleted file mode 100644
index 4dcc44a..0000000
--- a/osgi-launcher/pom.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
-
-    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.
-
--->
-<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.apache.taverna.osgi</groupId>
-      <artifactId>apache-taverna-osgi</artifactId>
-      <version>0.2.1-incubating-SNAPSHOT</version>
-       </parent>
-       <artifactId>osgi-launcher</artifactId>
-       <name>OSGi Framework Launcher</name>
-       <description>Launches an OSGi framework and handles loading and 
starting of OSGi bundles and Spring DM managed services</description>
-       <dependencies>
-               <dependency>
-                       <groupId>org.osgi</groupId>
-                       <artifactId>org.osgi.core</artifactId>
-                       <version>${osgi.core.version}</version>
-               </dependency>
-       </dependencies>
-</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/de79bd3c/osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
----------------------------------------------------------------------
diff --git 
a/osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java 
b/osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
deleted file mode 100644
index 2ae272f..0000000
--- 
a/osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
+++ /dev/null
@@ -1,430 +0,0 @@
-/**
- * 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.taverna.osgilauncher;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.logging.Logger;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.launch.Framework;
-import org.osgi.framework.launch.FrameworkFactory;
-
-/**
- * OSGi Framework launcher.
- *
- * Handles loading and starting of OSGi bundles and Spring DM managed services.
- *
- * An implementation of an OSGi Service Platform Release 4.1 (or higher) must 
be available on the
- * classpath.
- *
- * @author David Withers
- */
-public class OsgiLauncher {
-
-       /**
-        * Default boot delegation packages.
-        */
-       public static final String DEFAULT_BOOT_DELEGATION_PACKAGES = 
"sun.*,com.sun.*,java.*";
-
-       /**
-        * Default system packages.
-        */
-       public static final String DEFAULT_SYSTEM_PACKAGES = 
"com.sun.org.apache.xml.internal.utils";
-
-       /**
-        * Default time to wait for services to start up.
-        */
-       private static final long serviceLoadTimeoutSeconds = 30;
-
-       private static final Logger logger = 
Logger.getLogger(OsgiLauncher.class.getName());
-
-       private Framework framework;
-       private BundleContext context;
-
-       private Map<String, String> frameworkConfiguration = new 
HashMap<String, String>();
-       private List<URI> bundlesToInstall = new ArrayList<URI>();
-       private List<Bundle> installedBundles = new ArrayList<Bundle>();
-       private Set<String> startedSpringContexts = new HashSet<String>();
-       private Bundle springOsgiExtender;
-
-       private OsgiLauncher(File storageDirectory) {
-               setStorageDirectory(storageDirectory);
-               setCleanStorageDirectory(true);
-               setBootDelegationPackages(DEFAULT_BOOT_DELEGATION_PACKAGES);
-               setSystemPackages(DEFAULT_SYSTEM_PACKAGES);
-       }
-
-       /**
-        * Constructs an <code>OsgiLauncher</code> that loads bundles from a 
directory.
-        *
-        * Any file in the specified directory with a .jar extension will be 
loaded when the framework
-        * is started.
-        *
-        * @param storageDirectory
-        *            persistent storage area used by the framework
-        * @param storageDirectory
-        *            the directory containing bundles to load
-        */
-       public OsgiLauncher(File storageDirectory, File bundleDirectory) {
-               this(storageDirectory);
-               List<File> jars = Arrays.asList(bundleDirectory.listFiles(new 
FilenameFilter() {
-                       public boolean accept(File dir, String name) {
-                               return name.endsWith(".jar");
-                       }
-               }));
-               for (File jar : jars) {
-                       bundlesToInstall.add(jar.toURI());
-               }
-       }
-
-       /**
-        * Constructs an <code>OsgiLauncher</code> that loads the specified 
bundles.
-        *
-        * @param storageDirectory
-        *            persistent storage area used by the framework
-        * @param bundleURIs
-        *            bundles to load
-        */
-       public OsgiLauncher(File storageDirectory, List<URI> bundleURIs) {
-               this(storageDirectory);
-               for (URI bundleURI : bundleURIs) {
-                       bundlesToInstall.add(bundleURI);
-               }
-       }
-
-       /**
-        * Starts the OSGi framework, installs and starts the bundles.
-        *
-        * @throws BundleException
-        *             if the framework could not be started
-        */
-       public void start() throws BundleException {
-               logger.info("Loading the OSGi Framework Factory");
-               FrameworkFactory frameworkFactory = 
ServiceLoader.load(FrameworkFactory.class).iterator()
-                               .next();
-
-               logger.info("Creating the OSGi Framework");
-               framework = 
frameworkFactory.newFramework(frameworkConfiguration);
-               logger.info("Starting the OSGi Framework");
-               framework.start();
-
-               context = framework.getBundleContext();
-               context.addServiceListener(new ServiceListener() {
-                       public void serviceChanged(ServiceEvent event) {
-                               ServiceReference serviceReference = 
event.getServiceReference();
-                               if (event.getType() == ServiceEvent.REGISTERED) 
{
-                                       Object property = serviceReference
-                                                       
.getProperty("org.springframework.context.service.name");
-                                       if (property != null) {
-                                               
addStartedSpringContext(property.toString());
-                                       }
-                               }
-                               logger.fine((event.getType() == 
ServiceEvent.REGISTERED ? "Registering : "
-                                               : "Unregistering : ") + 
serviceReference);
-                       }
-               });
-
-               installedBundles = installBundles(bundlesToInstall);
-
-               List<Bundle> bundlesToStart = new ArrayList<Bundle>();
-               for (Bundle bundle : installedBundles) {
-                       if 
("org.springframework.osgi.extender".equals(bundle.getSymbolicName())) {
-                               springOsgiExtender = bundle;
-                       } else {
-                               bundlesToStart.add(bundle);
-                       }
-               }
-               startBundles(bundlesToStart);
-       }
-
-       /**
-        * Starts SpringDM managed services.
-        *
-        * @param waitForServices
-        *            if true waits for services to start before returning
-        * @throws BundleException
-        *             if the framework has not been started or a service could 
not be started
-        */
-       public void startServices(boolean waitForServices) throws 
BundleException {
-               if (framework == null || framework.getState() != Bundle.ACTIVE) 
{
-                       throw new BundleException("Framework not started");
-               }
-               if (springOsgiExtender != null) {
-                       logger.info("Starting Spring OSGi Extender");
-                       springOsgiExtender.start();
-                       if (waitForServices) {
-                               logger.info("Waiting for spring contexts to be 
started");
-                               for (Bundle bundle : installedBundles) {
-                                       if (bundle.getState() == Bundle.ACTIVE) 
{
-                                               if (hasSpringContext(bundle)) {
-                                                       logger.fine("Waiting 
for " + bundle.getSymbolicName());
-                                                       
waitForSpringContext(context, bundle.getSymbolicName(), 
serviceLoadTimeoutSeconds);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Stops the OSGI framework.
-        *
-        * @throws BundleException
-        *             if the framework has not been started
-        * @throws InterruptedException
-        *             if the thread is interrupted while the framework is 
stopping
-        */
-       public void stop() throws BundleException, InterruptedException {
-               if (framework == null || framework.getState() != Bundle.ACTIVE) 
{
-                       throw new BundleException("Framework not started");
-               }
-               framework.stop();
-               framework.waitForStop(0);
-               context = null;
-       }
-
-       /**
-        * Installs the bundles specified by the URIs into the framework.
-        *
-        * @param bundlesURIs
-        *            the URIs of the bundles to install
-        * @return the installed bundles
-        * @throws BundleException
-        *             if a bundle could not be installed
-        */
-       public List<Bundle> installBundles(List<URI> bundlesURIs) throws 
BundleException {
-               List<Bundle> installedBundles = new ArrayList<Bundle>();
-               logger.info("Installing bundles into the OSGi Framework");
-               for (URI bundleURI : bundlesURIs) {
-                       installedBundles.add(installBundle(bundleURI));
-               }
-               return installedBundles;
-       }
-
-       /**
-        * Installs the bundle specified by the URI into the framework.
-        *
-        * @param bundleURI
-        *            the URI of the bundle to install
-        * @return the installed bundle
-        * @throws BundleException
-        *             if the bundle could not be installed
-        */
-       public Bundle installBundle(URI bundleURI) throws BundleException {
-               logger.fine("Installing bundle " + bundleURI);
-               return context.installBundle(bundleURI.toASCIIString());
-       }
-
-       /**
-        * Starts the bundles.
-        *
-        * If a bundle is a fragment bundle that bundle is not started.
-        *
-        * @param bundles
-        *            the bundles to start
-        * @throws BundleException
-        *             if a bundle could not be started
-        */
-       public void startBundles(List<Bundle> bundles) throws BundleException {
-               logger.info("Starting bundles in the OSGi Framework");
-               for (Bundle bundle : bundles) {
-                       startBundle(bundle);
-               }
-       }
-
-       /**
-        * Starts the bundle.
-        *
-        * If the bundle is a fragment bundle the bundle is not started.
-        *
-        * @param bundle
-        *            the bundle to start
-        * @throws BundleException
-        *             if the bundle could not be started
-        */
-       public void startBundle(Bundle bundle) throws BundleException {
-               if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null) {
-                       logger.fine("Starting bundle " + bundle);
-                       bundle.start();
-               }
-       }
-
-       /**
-        * Returns the context. Returns <code>null</code> if the framework is 
not started.
-        *
-        * @return the context
-        */
-       public BundleContext getContext() {
-               return context;
-       }
-
-       /**
-        * Sets the configuration to use when creating the OSGi framework.
-        *
-        * @param frameworkConfiguration the configuration to use when creating 
the OSGi framework
-        */
-       public void setFrameworkConfiguration(Map<String, String> 
frameworkConfiguration) {
-               this.frameworkConfiguration = frameworkConfiguration;
-       }
-
-       /**
-        * Adds boot delegation packages.
-        *
-        * Multiple packages must be separated by a ','.
-        *
-        * @param additionalBootDelegationPackages
-        *            boot delegation packages to add
-        */
-       public void addBootDelegationPackages(String 
additionalBootDelegationPackages) {
-               String bootDelegationPackages = frameworkConfiguration
-                               .get(Constants.FRAMEWORK_BOOTDELEGATION);
-               if (bootDelegationPackages == null || 
bootDelegationPackages.isEmpty()) {
-                       bootDelegationPackages = 
additionalBootDelegationPackages;
-               } else {
-                       bootDelegationPackages = bootDelegationPackages + ","
-                                       + additionalBootDelegationPackages;
-               }
-               frameworkConfiguration.put(Constants.FRAMEWORK_BOOTDELEGATION, 
bootDelegationPackages);
-       }
-
-       /**
-        * Sets the boot delegation packages.
-        *
-        * Multiple packages must be separated by a ','.
-        *
-        * @param bootDelegationPackages
-        *            the boot delegation packages
-        */
-       public void setBootDelegationPackages(String bootDelegationPackages) {
-               frameworkConfiguration.put(Constants.FRAMEWORK_BOOTDELEGATION, 
bootDelegationPackages);
-       }
-
-       /**
-        * Adds system packages.
-        *
-        * Multiple packages must be separated by a ','.
-        *
-        * @param additionalSystemPackages
-        *            system packages to add
-        */
-       public void addSystemPackages(String additionalSystemPackages) {
-               String systemPackages = frameworkConfiguration
-                               .get(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
-               if (systemPackages == null || systemPackages.isEmpty()) {
-                       systemPackages = additionalSystemPackages;
-               } else {
-                       systemPackages = systemPackages + "," + 
additionalSystemPackages;
-               }
-               
frameworkConfiguration.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, 
systemPackages);
-       }
-
-       /**
-        * Sets the system packages.
-        *
-        * Multiple packages must be separated by a ','.
-        *
-        * @param systemPackages
-        *            the system packages
-        */
-       public void setSystemPackages(String systemPackages) {
-               
frameworkConfiguration.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, 
systemPackages);
-       }
-
-       /**
-        * Sets the persistent storage area used by the framework.
-        *
-        * @param storageDirectory the persistent storage area used by the 
framework
-        */
-       public void setStorageDirectory(File storageDirectory) {
-               frameworkConfiguration.put(Constants.FRAMEWORK_STORAGE, 
storageDirectory.getAbsolutePath());
-       }
-
-       /**
-        * Set whether the storage directory should be cleaned on startup.
-        *
-        * @param cleanStorageDirectory
-        *            whether the storage directory should be cleaned on startup
-        */
-       public void setCleanStorageDirectory(boolean cleanStorageDirectory) {
-               if (cleanStorageDirectory) {
-                       
frameworkConfiguration.put(Constants.FRAMEWORK_STORAGE_CLEAN,
-                                       
Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
-               } else {
-                       
frameworkConfiguration.remove(Constants.FRAMEWORK_STORAGE_CLEAN);
-               }
-       }
-
-       /**
-        * Returns true if a bundle contains spring context files.
-        *
-        * @param bundle
-        *            the bundle to check
-        * @return true if a bundle contains spring context files
-        */
-       private boolean hasSpringContext(Bundle bundle) {
-               String springFilesLocation = "META-INF/spring";
-               // check for custom spring files location
-               @SuppressWarnings("rawtypes")
-               Dictionary headers = bundle.getHeaders();
-               if (headers != null) {
-                       Object header = headers.get("Spring-Context");
-                       if (header != null) {
-                               springFilesLocation = header.toString().trim();
-                       }
-               }
-               @SuppressWarnings("rawtypes")
-               Enumeration springFiles = 
bundle.findEntries(springFilesLocation, "*.xml", false);
-               return springFiles != null && springFiles.hasMoreElements();
-       }
-
-       private synchronized void waitForSpringContext(BundleContext context, 
String springContext,
-                       long timeoutSeconds) {
-               long timeLeftToWait = timeoutSeconds * 1000;
-               long startTime = System.currentTimeMillis();
-
-               while (!startedSpringContexts.contains(springContext) && 
timeLeftToWait > 0) {
-                       try {
-                               wait(timeLeftToWait);
-                       } catch (InterruptedException e) {}
-                       timeLeftToWait = timeLeftToWait - 
(System.currentTimeMillis() - startTime);
-               }
-       }
-
-       private synchronized void addStartedSpringContext(String springContext) 
{
-               startedSpringContexts.add(springContext);
-               notifyAll();
-       }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/de79bd3c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f496138..bc8ac3d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,7 @@ command line/desktop product.</description>
        <modules>
                <module>xml-parser-service</module>
                <module>xml-transformer-service</module>
-               <module>osgi-launcher</module>
+               <module>taverna-osgi-launcher</module>
                <module>taverna-app-configuration-api</module>
                <module>taverna-app-configuration-impl</module>
                <module>taverna-configuration-api</module>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/de79bd3c/taverna-osgi-launcher/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-osgi-launcher/pom.xml b/taverna-osgi-launcher/pom.xml
new file mode 100644
index 0000000..af02144
--- /dev/null
+++ b/taverna-osgi-launcher/pom.xml
@@ -0,0 +1,36 @@
+<!--
+
+    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.
+
+-->
+<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.apache.taverna.osgi</groupId>
+      <artifactId>apache-taverna-osgi</artifactId>
+      <version>0.2.1-incubating-SNAPSHOT</version>
+       </parent>
+       <artifactId>taverna-osgi-launcher</artifactId>
+       <name>Apache Taverna OSGi Framework Launcher</name>
+       <description>Launches an OSGi framework and handles loading and 
starting of OSGi bundles and Spring DM managed services</description>
+       <dependencies>
+               <dependency>
+                       <groupId>org.osgi</groupId>
+                       <artifactId>org.osgi.core</artifactId>
+                       <version>${osgi.core.version}</version>
+               </dependency>
+       </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/de79bd3c/taverna-osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
----------------------------------------------------------------------
diff --git 
a/taverna-osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
 
b/taverna-osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
new file mode 100644
index 0000000..2ae272f
--- /dev/null
+++ 
b/taverna-osgi-launcher/src/main/java/org/apache/taverna/osgilauncher/OsgiLauncher.java
@@ -0,0 +1,430 @@
+/**
+ * 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.taverna.osgilauncher;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+/**
+ * OSGi Framework launcher.
+ *
+ * Handles loading and starting of OSGi bundles and Spring DM managed services.
+ *
+ * An implementation of an OSGi Service Platform Release 4.1 (or higher) must 
be available on the
+ * classpath.
+ *
+ * @author David Withers
+ */
+public class OsgiLauncher {
+
+       /**
+        * Default boot delegation packages.
+        */
+       public static final String DEFAULT_BOOT_DELEGATION_PACKAGES = 
"sun.*,com.sun.*,java.*";
+
+       /**
+        * Default system packages.
+        */
+       public static final String DEFAULT_SYSTEM_PACKAGES = 
"com.sun.org.apache.xml.internal.utils";
+
+       /**
+        * Default time to wait for services to start up.
+        */
+       private static final long serviceLoadTimeoutSeconds = 30;
+
+       private static final Logger logger = 
Logger.getLogger(OsgiLauncher.class.getName());
+
+       private Framework framework;
+       private BundleContext context;
+
+       private Map<String, String> frameworkConfiguration = new 
HashMap<String, String>();
+       private List<URI> bundlesToInstall = new ArrayList<URI>();
+       private List<Bundle> installedBundles = new ArrayList<Bundle>();
+       private Set<String> startedSpringContexts = new HashSet<String>();
+       private Bundle springOsgiExtender;
+
+       private OsgiLauncher(File storageDirectory) {
+               setStorageDirectory(storageDirectory);
+               setCleanStorageDirectory(true);
+               setBootDelegationPackages(DEFAULT_BOOT_DELEGATION_PACKAGES);
+               setSystemPackages(DEFAULT_SYSTEM_PACKAGES);
+       }
+
+       /**
+        * Constructs an <code>OsgiLauncher</code> that loads bundles from a 
directory.
+        *
+        * Any file in the specified directory with a .jar extension will be 
loaded when the framework
+        * is started.
+        *
+        * @param storageDirectory
+        *            persistent storage area used by the framework
+        * @param storageDirectory
+        *            the directory containing bundles to load
+        */
+       public OsgiLauncher(File storageDirectory, File bundleDirectory) {
+               this(storageDirectory);
+               List<File> jars = Arrays.asList(bundleDirectory.listFiles(new 
FilenameFilter() {
+                       public boolean accept(File dir, String name) {
+                               return name.endsWith(".jar");
+                       }
+               }));
+               for (File jar : jars) {
+                       bundlesToInstall.add(jar.toURI());
+               }
+       }
+
+       /**
+        * Constructs an <code>OsgiLauncher</code> that loads the specified 
bundles.
+        *
+        * @param storageDirectory
+        *            persistent storage area used by the framework
+        * @param bundleURIs
+        *            bundles to load
+        */
+       public OsgiLauncher(File storageDirectory, List<URI> bundleURIs) {
+               this(storageDirectory);
+               for (URI bundleURI : bundleURIs) {
+                       bundlesToInstall.add(bundleURI);
+               }
+       }
+
+       /**
+        * Starts the OSGi framework, installs and starts the bundles.
+        *
+        * @throws BundleException
+        *             if the framework could not be started
+        */
+       public void start() throws BundleException {
+               logger.info("Loading the OSGi Framework Factory");
+               FrameworkFactory frameworkFactory = 
ServiceLoader.load(FrameworkFactory.class).iterator()
+                               .next();
+
+               logger.info("Creating the OSGi Framework");
+               framework = 
frameworkFactory.newFramework(frameworkConfiguration);
+               logger.info("Starting the OSGi Framework");
+               framework.start();
+
+               context = framework.getBundleContext();
+               context.addServiceListener(new ServiceListener() {
+                       public void serviceChanged(ServiceEvent event) {
+                               ServiceReference serviceReference = 
event.getServiceReference();
+                               if (event.getType() == ServiceEvent.REGISTERED) 
{
+                                       Object property = serviceReference
+                                                       
.getProperty("org.springframework.context.service.name");
+                                       if (property != null) {
+                                               
addStartedSpringContext(property.toString());
+                                       }
+                               }
+                               logger.fine((event.getType() == 
ServiceEvent.REGISTERED ? "Registering : "
+                                               : "Unregistering : ") + 
serviceReference);
+                       }
+               });
+
+               installedBundles = installBundles(bundlesToInstall);
+
+               List<Bundle> bundlesToStart = new ArrayList<Bundle>();
+               for (Bundle bundle : installedBundles) {
+                       if 
("org.springframework.osgi.extender".equals(bundle.getSymbolicName())) {
+                               springOsgiExtender = bundle;
+                       } else {
+                               bundlesToStart.add(bundle);
+                       }
+               }
+               startBundles(bundlesToStart);
+       }
+
+       /**
+        * Starts SpringDM managed services.
+        *
+        * @param waitForServices
+        *            if true waits for services to start before returning
+        * @throws BundleException
+        *             if the framework has not been started or a service could 
not be started
+        */
+       public void startServices(boolean waitForServices) throws 
BundleException {
+               if (framework == null || framework.getState() != Bundle.ACTIVE) 
{
+                       throw new BundleException("Framework not started");
+               }
+               if (springOsgiExtender != null) {
+                       logger.info("Starting Spring OSGi Extender");
+                       springOsgiExtender.start();
+                       if (waitForServices) {
+                               logger.info("Waiting for spring contexts to be 
started");
+                               for (Bundle bundle : installedBundles) {
+                                       if (bundle.getState() == Bundle.ACTIVE) 
{
+                                               if (hasSpringContext(bundle)) {
+                                                       logger.fine("Waiting 
for " + bundle.getSymbolicName());
+                                                       
waitForSpringContext(context, bundle.getSymbolicName(), 
serviceLoadTimeoutSeconds);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Stops the OSGI framework.
+        *
+        * @throws BundleException
+        *             if the framework has not been started
+        * @throws InterruptedException
+        *             if the thread is interrupted while the framework is 
stopping
+        */
+       public void stop() throws BundleException, InterruptedException {
+               if (framework == null || framework.getState() != Bundle.ACTIVE) 
{
+                       throw new BundleException("Framework not started");
+               }
+               framework.stop();
+               framework.waitForStop(0);
+               context = null;
+       }
+
+       /**
+        * Installs the bundles specified by the URIs into the framework.
+        *
+        * @param bundlesURIs
+        *            the URIs of the bundles to install
+        * @return the installed bundles
+        * @throws BundleException
+        *             if a bundle could not be installed
+        */
+       public List<Bundle> installBundles(List<URI> bundlesURIs) throws 
BundleException {
+               List<Bundle> installedBundles = new ArrayList<Bundle>();
+               logger.info("Installing bundles into the OSGi Framework");
+               for (URI bundleURI : bundlesURIs) {
+                       installedBundles.add(installBundle(bundleURI));
+               }
+               return installedBundles;
+       }
+
+       /**
+        * Installs the bundle specified by the URI into the framework.
+        *
+        * @param bundleURI
+        *            the URI of the bundle to install
+        * @return the installed bundle
+        * @throws BundleException
+        *             if the bundle could not be installed
+        */
+       public Bundle installBundle(URI bundleURI) throws BundleException {
+               logger.fine("Installing bundle " + bundleURI);
+               return context.installBundle(bundleURI.toASCIIString());
+       }
+
+       /**
+        * Starts the bundles.
+        *
+        * If a bundle is a fragment bundle that bundle is not started.
+        *
+        * @param bundles
+        *            the bundles to start
+        * @throws BundleException
+        *             if a bundle could not be started
+        */
+       public void startBundles(List<Bundle> bundles) throws BundleException {
+               logger.info("Starting bundles in the OSGi Framework");
+               for (Bundle bundle : bundles) {
+                       startBundle(bundle);
+               }
+       }
+
+       /**
+        * Starts the bundle.
+        *
+        * If the bundle is a fragment bundle the bundle is not started.
+        *
+        * @param bundle
+        *            the bundle to start
+        * @throws BundleException
+        *             if the bundle could not be started
+        */
+       public void startBundle(Bundle bundle) throws BundleException {
+               if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null) {
+                       logger.fine("Starting bundle " + bundle);
+                       bundle.start();
+               }
+       }
+
+       /**
+        * Returns the context. Returns <code>null</code> if the framework is 
not started.
+        *
+        * @return the context
+        */
+       public BundleContext getContext() {
+               return context;
+       }
+
+       /**
+        * Sets the configuration to use when creating the OSGi framework.
+        *
+        * @param frameworkConfiguration the configuration to use when creating 
the OSGi framework
+        */
+       public void setFrameworkConfiguration(Map<String, String> 
frameworkConfiguration) {
+               this.frameworkConfiguration = frameworkConfiguration;
+       }
+
+       /**
+        * Adds boot delegation packages.
+        *
+        * Multiple packages must be separated by a ','.
+        *
+        * @param additionalBootDelegationPackages
+        *            boot delegation packages to add
+        */
+       public void addBootDelegationPackages(String 
additionalBootDelegationPackages) {
+               String bootDelegationPackages = frameworkConfiguration
+                               .get(Constants.FRAMEWORK_BOOTDELEGATION);
+               if (bootDelegationPackages == null || 
bootDelegationPackages.isEmpty()) {
+                       bootDelegationPackages = 
additionalBootDelegationPackages;
+               } else {
+                       bootDelegationPackages = bootDelegationPackages + ","
+                                       + additionalBootDelegationPackages;
+               }
+               frameworkConfiguration.put(Constants.FRAMEWORK_BOOTDELEGATION, 
bootDelegationPackages);
+       }
+
+       /**
+        * Sets the boot delegation packages.
+        *
+        * Multiple packages must be separated by a ','.
+        *
+        * @param bootDelegationPackages
+        *            the boot delegation packages
+        */
+       public void setBootDelegationPackages(String bootDelegationPackages) {
+               frameworkConfiguration.put(Constants.FRAMEWORK_BOOTDELEGATION, 
bootDelegationPackages);
+       }
+
+       /**
+        * Adds system packages.
+        *
+        * Multiple packages must be separated by a ','.
+        *
+        * @param additionalSystemPackages
+        *            system packages to add
+        */
+       public void addSystemPackages(String additionalSystemPackages) {
+               String systemPackages = frameworkConfiguration
+                               .get(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+               if (systemPackages == null || systemPackages.isEmpty()) {
+                       systemPackages = additionalSystemPackages;
+               } else {
+                       systemPackages = systemPackages + "," + 
additionalSystemPackages;
+               }
+               
frameworkConfiguration.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, 
systemPackages);
+       }
+
+       /**
+        * Sets the system packages.
+        *
+        * Multiple packages must be separated by a ','.
+        *
+        * @param systemPackages
+        *            the system packages
+        */
+       public void setSystemPackages(String systemPackages) {
+               
frameworkConfiguration.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, 
systemPackages);
+       }
+
+       /**
+        * Sets the persistent storage area used by the framework.
+        *
+        * @param storageDirectory the persistent storage area used by the 
framework
+        */
+       public void setStorageDirectory(File storageDirectory) {
+               frameworkConfiguration.put(Constants.FRAMEWORK_STORAGE, 
storageDirectory.getAbsolutePath());
+       }
+
+       /**
+        * Set whether the storage directory should be cleaned on startup.
+        *
+        * @param cleanStorageDirectory
+        *            whether the storage directory should be cleaned on startup
+        */
+       public void setCleanStorageDirectory(boolean cleanStorageDirectory) {
+               if (cleanStorageDirectory) {
+                       
frameworkConfiguration.put(Constants.FRAMEWORK_STORAGE_CLEAN,
+                                       
Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
+               } else {
+                       
frameworkConfiguration.remove(Constants.FRAMEWORK_STORAGE_CLEAN);
+               }
+       }
+
+       /**
+        * Returns true if a bundle contains spring context files.
+        *
+        * @param bundle
+        *            the bundle to check
+        * @return true if a bundle contains spring context files
+        */
+       private boolean hasSpringContext(Bundle bundle) {
+               String springFilesLocation = "META-INF/spring";
+               // check for custom spring files location
+               @SuppressWarnings("rawtypes")
+               Dictionary headers = bundle.getHeaders();
+               if (headers != null) {
+                       Object header = headers.get("Spring-Context");
+                       if (header != null) {
+                               springFilesLocation = header.toString().trim();
+                       }
+               }
+               @SuppressWarnings("rawtypes")
+               Enumeration springFiles = 
bundle.findEntries(springFilesLocation, "*.xml", false);
+               return springFiles != null && springFiles.hasMoreElements();
+       }
+
+       private synchronized void waitForSpringContext(BundleContext context, 
String springContext,
+                       long timeoutSeconds) {
+               long timeLeftToWait = timeoutSeconds * 1000;
+               long startTime = System.currentTimeMillis();
+
+               while (!startedSpringContexts.contains(springContext) && 
timeLeftToWait > 0) {
+                       try {
+                               wait(timeLeftToWait);
+                       } catch (InterruptedException e) {}
+                       timeLeftToWait = timeLeftToWait - 
(System.currentTimeMillis() - startTime);
+               }
+       }
+
+       private synchronized void addStartedSpringContext(String springContext) 
{
+               startedSpringContexts.add(springContext);
+               notifyAll();
+       }
+
+}

Reply via email to