map) throws ConfigurationException;
}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/SpringOsgiObjectFactory.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/SpringOsgiObjectFactory.java
index 4e595764e..3cebb328e 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/SpringOsgiObjectFactory.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/SpringOsgiObjectFactory.java
@@ -33,6 +33,7 @@ import java.util.Map;
* to lookup beans
*/
public class SpringOsgiObjectFactory extends ObjectFactory {
+
private final static String SPRING_SERVICE_NAME = "org.springframework.context.ApplicationContext";
private BundleAccessor bundleAccessor;
@@ -88,4 +89,5 @@ public class SpringOsgiObjectFactory extends ObjectFactory {
public void setBundleAccessor(BundleAccessor bundleAccessor) {
this.bundleAccessor = bundleAccessor;
}
+
}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java
index ec1c322ec..31b980f0c 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java
@@ -1,26 +1,39 @@
package org.apache.struts2.osgi;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.StrutsException;
+import org.apache.struts2.osgi.host.OsgiHost;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
/**
- * ServletContextListener that starts Apache Felix
+ * ServletContextListener that starts Osgi host
*/
public class StrutsOsgiListener implements ServletContextListener {
+
public static final String OSGI_HOST = "__struts_osgi_host";
- private FelixOsgiHost osgiHost;
+ public static final String PLATFORM_KEY = "struts.osgi.host";
+
+ private static final Logger LOG = LoggerFactory.getLogger(StrutsOsgiListener.class);
+
+ private OsgiHost osgiHost;
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
- osgiHost = new FelixOsgiHost();
+
+ String platform = servletContext.getInitParameter(PLATFORM_KEY);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Defined OSGi platform as [#0] via context-param [#1]", platform, PLATFORM_KEY);
+ }
+ osgiHost = OsgiHostFactory.createOsgiHost(platform);
servletContext.setAttribute(OSGI_HOST, osgiHost);
try {
osgiHost.init(servletContext);
} catch (Exception e) {
- throw new StrutsException("Apache Felix failed to start", e);
+ throw new StrutsException("Cannot init OSGi platform!", e);
}
}
@@ -28,7 +41,8 @@ public class StrutsOsgiListener implements ServletContextListener {
try {
osgiHost.destroy();
} catch (Exception e) {
- throw new StrutsException("Apache Felix failed to stop", e);
+ throw new StrutsException("Cannot stop OSGi platform!", e);
}
}
-}
+
+}
\ No newline at end of file
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/BaseOsgiHost.java
similarity index 62%
rename from plugins/osgi/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java
rename to plugins/osgi/src/main/java/org/apache/struts2/osgi/host/BaseOsgiHost.java
index 98ed5c390..0670a2134 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/BaseOsgiHost.java
@@ -1,427 +1,329 @@
-/*
- * $Id$
- *
- * 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.struts2.osgi;
-
-import com.opensymphony.xwork2.FileManager;
-import com.opensymphony.xwork2.FileManagerFactory;
-import com.opensymphony.xwork2.config.ConfigurationException;
-import com.opensymphony.xwork2.util.finder.ResourceFinder;
-import com.opensymphony.xwork2.util.logging.Logger;
-import com.opensymphony.xwork2.util.logging.LoggerFactory;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.felix.framework.Felix;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.main.AutoActivator;
-import org.apache.felix.main.Main;
-import org.apache.felix.shell.ShellService;
-import org.apache.struts2.ServletActionContext;
-import org.apache.struts2.StrutsException;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.util.tracker.ServiceTracker;
-
-import javax.servlet.ServletContext;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.net.URL;
-import java.security.CodeSource;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Apache felix implementation of an OsgiHost
- * See http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html
- *
- * Servlet config params:
- * struts.osgi.clearBundleCache: Defaults to "true" delete installed bundles when the comntainer starts
- * struts.osgi.logLevel: Defaults to "1". Felix log level. 1 = error, 2 = warning, 3 = information, and 4 = debug
- * struts.osgi.runLevel: Defaults to "3". Run level to start the container.
- */
-public class FelixOsgiHost implements OsgiHost {
- private static final Logger LOG = LoggerFactory.getLogger(FelixOsgiHost.class);
-
- private Felix felix;
- private static final Pattern versionPattern = Pattern.compile("([\\d])+[\\.-]");
- private ServletContext servletContext;
-
- protected void startFelix() {
- //load properties from felix embedded file
- Properties configProps = getProperties("default.properties");
-
- // Copy framework properties from the system properties.
- Main.copySystemProperties(configProps);
- replaceSystemPackages(configProps);
-
- //struts, xwork and felix exported packages
- Properties strutsConfigProps = getProperties("struts-osgi.properties");
- addExportedPackages(strutsConfigProps, configProps);
-
- //find bundles and adde em to autostart property
- addAutoStartBundles(configProps);
-
- // Bundle cache
- String storageDir = System.getProperty("java.io.tmpdir") + ".felix-cache";
- configProps.setProperty(Constants.FRAMEWORK_STORAGE, storageDir);
- if (LOG.isDebugEnabled())
- LOG.debug("Storing bundles at [#0]", storageDir);
-
- String cleanBundleCache = getServletContextParam("struts.osgi.clearBundleCache", "true");
- if ("true".equalsIgnoreCase(cleanBundleCache)) {
- if (LOG.isDebugEnabled())
- LOG.debug("Clearing bundle cache");
- configProps.put(FelixConstants.FRAMEWORK_STORAGE_CLEAN, FelixConstants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
- }
-
- //other properties
- configProps.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false");
- configProps.put(FelixConstants.LOG_LEVEL_PROP, getServletContextParam("struts.osgi.logLevel", "1"));
- configProps.put(FelixConstants.BUNDLE_CLASSPATH, ".");
- configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, getServletContextParam("struts.osgi.runLevel", "3"));
-
- try {
- List list = new ArrayList();
- list.add(new AutoActivator(configProps));
- configProps.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
-
- felix = new Felix(configProps);
- felix.start();
- if (LOG.isTraceEnabled())
- LOG.trace("Apache Felix is running");
- }
- catch (Exception ex) {
- throw new ConfigurationException("Couldn't start Apache Felix", ex);
- }
-
- addSpringOSGiSupport();
-
- //add the bundle context to the ServletContext
- servletContext.setAttribute(OSGI_BUNDLE_CONTEXT, felix.getBundleContext());
- }
-
- /**
- * Gets a param from the ServletContext, returning the default value if the param is not set
- *
- * @param paramName the name of the param to get from the ServletContext
- * @param defaultValue value to return if the param is not set
- * @return
- */
- private String getServletContextParam(String paramName, String defaultValue) {
- return StringUtils.defaultString(this.servletContext.getInitParameter(paramName), defaultValue);
- }
-
- protected void addAutoStartBundles(Properties configProps) {
- //starts system bundles in level 1
- List bundleJarsLevel1 = new ArrayList();
- bundleJarsLevel1.add(getJarUrl(ShellService.class));
- bundleJarsLevel1.add(getJarUrl(ServiceTracker.class));
- configProps.put(AutoActivator.AUTO_START_PROP + ".1", StringUtils.join(bundleJarsLevel1, " "));
-
- //get a list of directories under /bundles with numeric names (the runlevel)
- Map runLevels = getRunLevelDirs("bundles");
- if (runLevels.isEmpty()) {
- //there are no run level dirs, search for bundles in that dir
- List bundles = getBundlesInDir("bundles");
- if (!bundles.isEmpty())
- configProps.put(AutoActivator.AUTO_START_PROP + ".2", StringUtils.join(bundles, " "));
- } else {
- for (String runLevel : runLevels.keySet()) {
- if ("1".endsWith(runLevel))
- throw new StrutsException("Run level dirs must be greater than 1. Run level 1 is reserved for the Felix bundles");
- List bundles = getBundlesInDir(runLevels.get(runLevel));
- configProps.put(AutoActivator.AUTO_START_PROP + "." + runLevel, StringUtils.join(bundles, " "));
- }
- }
- }
-
- /**
- * Return a list of directories under a directory whose name is a number
- */
- protected Map getRunLevelDirs(String dir) {
- Map dirs = new HashMap();
- try {
- ResourceFinder finder = new ResourceFinder();
- URL url = finder.find("bundles");
- if (url != null) {
- if ("file".equals(url.getProtocol())) {
- File bundlesDir = new File(url.toURI());
- String[] runLevelDirs = bundlesDir.list(new FilenameFilter() {
- public boolean accept(File file, String name) {
- try {
- return file.isDirectory() && Integer.valueOf(name) > 0;
- } catch (NumberFormatException ex) {
- //the name is not a number
- return false;
- }
- }
- });
-
- if (runLevelDirs != null && runLevelDirs.length > 0) {
- //add all the dirs to the list
- for (String runLevel : runLevelDirs)
- dirs.put(runLevel, StringUtils.chomp(dir, "/") + "/" + runLevel);
-
- } else if (LOG.isDebugEnabled()) {
- LOG.debug("No run level directories found under the [#0] directory", dir);
- }
- } else if (LOG.isWarnEnabled())
- LOG.warn("Unable to read [#0] directory", dir);
- } else if (LOG.isWarnEnabled())
- LOG.warn("The [#0] directory was not found", dir);
- } catch (Exception e) {
- if (LOG.isWarnEnabled())
- LOG.warn("Unable load bundles from the [#0] directory", e, dir);
- }
- return dirs;
- }
-
- protected List getBundlesInDir(String dir) {
- List bundleJars = new ArrayList();
- try {
-
- ResourceFinder finder = new ResourceFinder();
- URL url = finder.find(dir);
- if (url != null) {
- if ("file".equals(url.getProtocol())) {
- File bundlesDir = new File(url.toURI());
- File[] bundles = bundlesDir.listFiles(new FilenameFilter() {
- public boolean accept(File file, String name) {
- return StringUtils.endsWith(name, ".jar");
- }
- });
-
- if (bundles != null && bundles.length > 0) {
- //add all the bundles to the list
- for (File bundle : bundles) {
- String externalForm = bundle.toURI().toURL().toExternalForm();
- if (LOG.isDebugEnabled()) {
- LOG.debug("Adding bundle [#0]", externalForm);
- }
- bundleJars.add(externalForm);
- }
-
- } else if (LOG.isDebugEnabled()) {
- LOG.debug("No bundles found under the [#0] directory", dir);
- }
- } else if (LOG.isWarnEnabled())
- LOG.warn("Unable to read [#0] directory", dir);
- } else if (LOG.isWarnEnabled())
- LOG.warn("The [#0] directory was not found", dir);
- } catch (Exception e) {
- if (LOG.isWarnEnabled())
- LOG.warn("Unable load bundles from the [#0] directory", e, dir);
- }
- return bundleJars;
- }
-
- protected void addSpringOSGiSupport() {
- // see the javadoc for org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext for more details
- // OsgiBundleXmlWebApplicationContext expects the the BundleContext to be set in the ServletContext under the attribute
- // OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE
- try {
- Class clazz = Class.forName("org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext");
- String key = (String) clazz.getDeclaredField("BUNDLE_CONTEXT_ATTRIBUTE").get(null);
- servletContext.setAttribute(key, felix.getBundleContext());
- } catch (ClassNotFoundException e) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Spring OSGi support is not enabled");
- }
- } catch (Exception e) {
- if (LOG.isErrorEnabled()) {
- LOG.error("The API of Spring OSGi has changed and the field [#0] is no longer available. The OSGi plugin needs to be updated", e,
- "org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE");
- }
- }
- }
-
- protected String getJarUrl(Class clazz) {
- ProtectionDomain protectionDomain = clazz.getProtectionDomain();
- CodeSource codeSource = protectionDomain.getCodeSource();
- URL loc = codeSource.getLocation();
- return loc.toString();
- }
-
- protected void replaceSystemPackages(Properties properties) {
- //Felix has a way to load the config file and substitution expressions
- //but the method does not have a way to specify the file (other than in an env variable)
-
- //${jre-${java.specification.version}}
- String systemPackages = (String) properties.get(Constants.FRAMEWORK_SYSTEMPACKAGES);
- String jreVersion = "jre-" + System.getProperty("java.version").substring(0, 3);
- systemPackages = systemPackages.replace("${jre-${java.specification.version}}", (String) properties.get(jreVersion));
- properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages);
- }
-
- /*
- Find subpackages of the packages defined in the property file and export them
- */
- protected void addExportedPackages(Properties strutsConfigProps, Properties configProps) {
- String[] rootPackages = StringUtils.split((String) strutsConfigProps.get("scanning.package.includes"), ",");
- ResourceFinder finder = new ResourceFinder(StringUtils.EMPTY);
- List exportedPackages = new ArrayList();
- //build a list of subpackages
- for (String rootPackage : rootPackages) {
- try {
- String version = null;
- if (rootPackage.indexOf(";") > 0) {
- String[] splitted = rootPackage.split(";");
- rootPackage = splitted[0];
- version = splitted[1];
- }
- Map> subpackagesMap = finder.findPackagesMap(StringUtils.replace(rootPackage.trim(), ".", "/"));
- for (Map.Entry> entry : subpackagesMap.entrySet()) {
- URL url = entry.getKey();
- Set packages = entry.getValue();
-
- //get version if not set
- if (StringUtils.isBlank(version))
- version = getVersion(url);
-
- if (packages != null) {
- for (String subpackage : packages) {
- exportedPackages.add(subpackage + "; version=" + version);
- }
- }
- }
- } catch (IOException e) {
- if (LOG.isErrorEnabled())
- LOG.error("Unable to find subpackages of [#0]", e, rootPackage);
- }
- }
-
- //make a string with the exported packages and add it to the system properties
- if (!exportedPackages.isEmpty()) {
- String systemPackages = (String) configProps.get(Constants.FRAMEWORK_SYSTEMPACKAGES);
- systemPackages = StringUtils.chomp(systemPackages, ",") + "," + StringUtils.join(exportedPackages, ",");
- configProps.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages);
- }
- }
-
- /**
- * Gets the version used to export the packages. it tries to get it from MANIFEST.MF, or the file name
- */
- protected String getVersion(URL url) {
- if ("jar".equals(url.getProtocol())) {
- try {
- FileManager fileManager = ServletActionContext.getContext().getInstance(FileManagerFactory.class).getFileManager();
- JarFile jarFile = new JarFile(new File(fileManager.normalizeToFileProtocol(url).toURI()));
- Manifest manifest = jarFile.getManifest();
- if (manifest != null) {
- String version = manifest.getMainAttributes().getValue("Bundle-Version");
- if (StringUtils.isNotBlank(version)) {
- return getVersionFromString(version);
- }
- } else {
- //try to get the version from the file name
- return getVersionFromString(jarFile.getName());
- }
- } catch (Exception e) {
- if (LOG.isErrorEnabled())
- LOG.error("Unable to extract version from [#0], defaulting to '1.0.0'", url.toExternalForm());
-
- }
- }
-
- return "1.0.0";
- }
-
- /**
- * Extracts numbers followed by "." or "-" from the string and joins them with "."
- */
- protected static String getVersionFromString(String str) {
- Matcher matcher = versionPattern.matcher(str);
- List parts = new ArrayList();
- while (matcher.find()) {
- parts.add(matcher.group(1));
- }
-
- //default
- if (parts.size() == 0)
- return "1.0.0";
-
- while (parts.size() < 3)
- parts.add("0");
-
- return StringUtils.join(parts, ".");
- }
-
- protected Properties getProperties(String fileName) {
- ResourceFinder finder = new ResourceFinder("");
- try {
- return finder.findProperties(fileName);
- } catch (IOException e) {
- if (LOG.isErrorEnabled())
- LOG.error("Unable to read property file [#]", fileName);
- return new Properties();
- }
- }
-
- /**
- * This bundle map will not change, but the status of the bundles can change over time.
- * Use getActiveBundles() for active bundles
- */
- public Map getBundles() {
- Map bundles = new HashMap();
- for (Bundle bundle : felix.getBundleContext().getBundles()) {
- bundles.put(bundle.getSymbolicName(), bundle);
- }
-
- return Collections.unmodifiableMap(bundles);
- }
-
- public Map getActiveBundles() {
- Map bundles = new HashMap();
- for (Bundle bundle : felix.getBundleContext().getBundles()) {
- if (bundle.getState() == Bundle.ACTIVE)
- bundles.put(bundle.getSymbolicName(), bundle);
- }
-
- return Collections.unmodifiableMap(bundles);
- }
-
- public BundleContext getBundleContext() {
- return felix.getBundleContext();
- }
-
- public void destroy() throws Exception {
- felix.stop();
- if (LOG.isTraceEnabled())
- LOG.trace("Apache Felix has stopped");
- }
-
- public void init(ServletContext servletContext) {
- this.servletContext = servletContext;
- startFelix();
- }
-}
+/*
+ * $Id$
+ *
+ * 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.struts2.osgi.host;
+
+import com.opensymphony.xwork2.FileManager;
+import com.opensymphony.xwork2.FileManagerFactory;
+import com.opensymphony.xwork2.util.finder.ResourceFinder;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.main.AutoProcessor;
+import org.apache.felix.shell.ShellService;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.util.tracker.ServiceTracker;
+
+import javax.servlet.ServletContext;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A base OsgiHost implementation
+ */
+public abstract class BaseOsgiHost implements OsgiHost {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BaseOsgiHost.class);
+
+ protected static final Pattern versionPattern = Pattern.compile("([\\d])+[\\.-]");
+
+ protected ServletContext servletContext;
+
+ public abstract void init(ServletContext servletContext);
+
+ public abstract void destroy() throws Exception;
+
+ /**
+ * This bundle map will not change, but the status of the bundles can change over time.
+ * Use getActiveBundles() for active bundles
+ */
+ public abstract Map getBundles();
+
+ public abstract Map getActiveBundles();
+
+ public abstract BundleContext getBundleContext();
+
+ protected abstract void addSpringOSGiSupport();
+
+ /**
+ * Gets a param from the ServletContext, returning the default value if the param is not set
+ *
+ * @param paramName the name of the param to get from the ServletContext
+ * @param defaultValue value to return if the param is not set
+ * @return
+ */
+ protected String getServletContextParam(String paramName, String defaultValue) {
+ return StringUtils.defaultString(this.servletContext.getInitParameter(paramName), defaultValue);
+ }
+
+ protected void addAutoStartBundles(Properties configProps) {
+ //starts system bundles in level 1
+ List bundleJarsLevel1 = new ArrayList();
+ bundleJarsLevel1.add(getJarUrl(ShellService.class));
+ bundleJarsLevel1.add(getJarUrl(ServiceTracker.class));
+
+ configProps.put(AutoProcessor.AUTO_START_PROP + ".1", StringUtils.join(bundleJarsLevel1, " "));
+
+ //get a list of directories under /bundles with numeric names (the runlevel)
+ Map runLevels = getRunLevelDirs("bundles");
+ if (runLevels.isEmpty()) {
+ //there are no run level dirs, search for bundles in that dir
+ List bundles = getBundlesInDir("bundles");
+ if (!bundles.isEmpty()) {
+ configProps.put(AutoProcessor.AUTO_START_PROP + ".2", StringUtils.join(bundles, " "));
+ }
+ } else {
+ for (String runLevel : runLevels.keySet()) {
+ if ("1".endsWith(runLevel)) {
+ throw new StrutsException("Run level dirs must be greater than 1. Run level 1 is reserved for the Felix bundles");
+ }
+ List bundles = getBundlesInDir(runLevels.get(runLevel));
+ configProps.put(AutoProcessor.AUTO_START_PROP + "." + runLevel, StringUtils.join(bundles, " "));
+ }
+ }
+ }
+
+ /**
+ * Return a list of directories under a directory whose name is a number
+ */
+ protected Map getRunLevelDirs(String dir) {
+ Map dirs = new HashMap();
+ try {
+ ResourceFinder finder = new ResourceFinder();
+ URL url = finder.find("bundles");
+ if (url != null) {
+ if ("file".equals(url.getProtocol())) {
+ File bundlesDir = new File(url.toURI());
+ String[] runLevelDirs = bundlesDir.list(new FilenameFilter() {
+ public boolean accept(File file, String name) {
+ try {
+ return file.isDirectory() && Integer.valueOf(name) > 0;
+ } catch (NumberFormatException ex) {
+ //the name is not a number
+ return false;
+ }
+ }
+ });
+
+ if (runLevelDirs != null && runLevelDirs.length > 0) {
+ //add all the dirs to the list
+ for (String runLevel : runLevelDirs) {
+ dirs.put(runLevel, StringUtils.chomp(dir, "/") + "/" + runLevel);
+ }
+ } else if (LOG.isDebugEnabled()) {
+ LOG.debug("No run level directories found under the [#0] directory", dir);
+ }
+ } else if (LOG.isWarnEnabled()) {
+ LOG.warn("Unable to read [#0] directory", dir);
+ }
+ } else if (LOG.isWarnEnabled()) {
+ LOG.warn("The [#0] directory was not found", dir);
+ }
+ } catch (Exception e) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Unable load bundles from the [#0] directory", e, dir);
+ }
+ }
+ return dirs;
+ }
+
+ protected List getBundlesInDir(String dir) {
+ List bundleJars = new ArrayList();
+ try {
+ ResourceFinder finder = new ResourceFinder();
+ URL url = finder.find(dir);
+ if (url != null) {
+ if ("file".equals(url.getProtocol())) {
+ File bundlesDir = new File(url.toURI());
+ File[] bundles = bundlesDir.listFiles(new FilenameFilter() {
+ public boolean accept(File file, String name) {
+ return StringUtils.endsWith(name, ".jar");
+ }
+ });
+
+ if (bundles != null && bundles.length > 0) {
+ //add all the bundles to the list
+ for (File bundle : bundles) {
+ String externalForm = bundle.toURI().toURL().toExternalForm();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Adding bundle [#0]", externalForm);
+ }
+ bundleJars.add(externalForm);
+ }
+
+ } else if (LOG.isDebugEnabled()) {
+ LOG.debug("No bundles found under the [#0] directory", dir);
+ }
+ } else if (LOG.isWarnEnabled()) {
+ LOG.warn("Unable to read [#0] directory", dir);
+ }
+ } else if (LOG.isWarnEnabled()) {
+ LOG.warn("The [#0] directory was not found", dir);
+ }
+ } catch (Exception e) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Unable load bundles from the [#0] directory", e, dir);
+ }
+ }
+ return bundleJars;
+ }
+
+ protected String getJarUrl(Class clazz) {
+ ProtectionDomain protectionDomain = clazz.getProtectionDomain();
+ CodeSource codeSource = protectionDomain.getCodeSource();
+ URL loc = codeSource.getLocation();
+ return loc.toString();
+ }
+
+ protected void replaceSystemPackages(Properties properties) {
+ //Felix has a way to load the config file and substitution expressions
+ //but the method does not have a way to specify the file (other than in an env variable)
+
+ //${jre-${java.specification.version}}
+ String systemPackages = (String) properties.get(Constants.FRAMEWORK_SYSTEMPACKAGES);
+ String jreVersion = "jre-" + System.getProperty("java.version").substring(0, 3);
+ systemPackages = systemPackages.replace("${jre-${java.specification.version}}", (String) properties.get(jreVersion));
+ properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages);
+ }
+
+ /*
+ Find subpackages of the packages defined in the property file and export them
+ */
+ protected void addExportedPackages(Properties strutsConfigProps, Properties configProps) {
+ String[] rootPackages = StringUtils.split((String) strutsConfigProps.get("scanning.package.includes"), ",");
+ ResourceFinder finder = new ResourceFinder(StringUtils.EMPTY);
+ List exportedPackages = new ArrayList();
+ //build a list of subpackages
+ for (String rootPackage : rootPackages) {
+ try {
+ String version = null;
+ if (rootPackage.indexOf(";") > 0) {
+ String[] splitted = rootPackage.split(";");
+ rootPackage = splitted[0];
+ version = splitted[1];
+ }
+ Map> subpackagesMap = finder.findPackagesMap(StringUtils.replace(rootPackage.trim(), ".", "/"));
+ for (Map.Entry> entry : subpackagesMap.entrySet()) {
+ URL url = entry.getKey();
+ Set packages = entry.getValue();
+
+ //get version if not set
+ if (StringUtils.isBlank(version)) {
+ version = getVersion(url);
+ }
+
+ if (packages != null) {
+ for (String subpackage : packages) {
+ exportedPackages.add(subpackage + "; version=" + version);
+ }
+ }
+ }
+ } catch (IOException e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error("Unable to find subpackages of [#0]", e, rootPackage);
+ }
+ }
+ }
+
+ //make a string with the exported packages and add it to the system properties
+ if (!exportedPackages.isEmpty()) {
+ String systemPackages = (String) configProps.get(Constants.FRAMEWORK_SYSTEMPACKAGES);
+ systemPackages = StringUtils.chomp(systemPackages, ",") + "," + StringUtils.join(exportedPackages, ",");
+ configProps.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages);
+ }
+ }
+
+ /**
+ * Gets the version used to export the packages. it tries to get it from MANIFEST.MF, or the file name
+ */
+ protected String getVersion(URL url) {
+ if ("jar".equals(url.getProtocol())) {
+ try {
+ FileManager fileManager = ServletActionContext.getContext().getInstance(FileManagerFactory.class).getFileManager();
+ JarFile jarFile = new JarFile(new File(fileManager.normalizeToFileProtocol(url).toURI()));
+ Manifest manifest = jarFile.getManifest();
+ if (manifest != null) {
+ String version = manifest.getMainAttributes().getValue("Bundle-Version");
+ if (StringUtils.isNotBlank(version)) {
+ return getVersionFromString(version);
+ }
+ } else {
+ //try to get the version from the file name
+ return getVersionFromString(jarFile.getName());
+ }
+ } catch (Exception e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error("Unable to extract version from [#0], defaulting to '1.0.0'", url.toExternalForm());
+ }
+ }
+ }
+ return "1.0.0";
+ }
+
+ /**
+ * Extracts numbers followed by "." or "-" from the string and joins them with "."
+ */
+ protected String getVersionFromString(String str) {
+ Matcher matcher = versionPattern.matcher(str);
+ List parts = new ArrayList();
+ while (matcher.find()) {
+ parts.add(matcher.group(1));
+ }
+ //default
+ if (parts.size() == 0) {
+ return "1.0.0";
+ }
+ while (parts.size() < 3) {
+ parts.add("0");
+ }
+ return StringUtils.join(parts, ".");
+ }
+
+ protected Properties getProperties(String fileName) {
+ ResourceFinder finder = new ResourceFinder("");
+ try {
+ return finder.findProperties(fileName);
+ } catch (IOException e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error("Unable to read property file [#]", fileName);
+ }
+ return new Properties();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/FelixOsgiHost.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/FelixOsgiHost.java
new file mode 100644
index 000000000..77d2614cc
--- /dev/null
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/FelixOsgiHost.java
@@ -0,0 +1,173 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.osgi.host;
+
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+import org.apache.felix.framework.Felix;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.main.AutoProcessor;
+import org.apache.felix.main.Main;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+import javax.servlet.ServletContext;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Apache felix implementation of an OsgiHost
+ * See http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html
+ *
+ * Servlet config params:
+ * struts.osgi.clearBundleCache: Defaults to "true" delete installed bundles when the comntainer starts
+ * struts.osgi.logLevel: Defaults to "1". Felix log level. 1 = error, 2 = warning, 3 = information, and 4 = debug
+ * struts.osgi.runLevel: Defaults to "3". Run level to start the container.
+ */
+public class FelixOsgiHost extends BaseOsgiHost {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FelixOsgiHost.class);
+
+ protected Felix felix;
+
+ protected void startFelix() {
+ //load properties from felix embedded file
+ Properties configProps = getProperties("default.properties");
+
+ // Copy framework properties from the system properties.
+ Main.copySystemProperties(configProps);
+ replaceSystemPackages(configProps);
+
+ //struts, xwork and felix exported packages
+ Properties strutsConfigProps = getProperties("struts-osgi.properties");
+ addExportedPackages(strutsConfigProps, configProps);
+
+ //find bundles and adde em to autostart property
+ addAutoStartBundles(configProps);
+
+ // Bundle cache
+ String storageDir = System.getProperty("java.io.tmpdir") + ".felix-cache";
+ configProps.setProperty(Constants.FRAMEWORK_STORAGE, storageDir);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Storing bundles at [#0]", storageDir);
+
+ String cleanBundleCache = getServletContextParam("struts.osgi.clearBundleCache", "true");
+ if ("true".equalsIgnoreCase(cleanBundleCache)) {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Clearing bundle cache");
+ configProps.put(FelixConstants.FRAMEWORK_STORAGE_CLEAN, FelixConstants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
+ }
+
+ //other properties
+ configProps.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false");
+ configProps.put(FelixConstants.LOG_LEVEL_PROP, getServletContextParam("struts.osgi.logLevel", "1"));
+ configProps.put(FelixConstants.BUNDLE_CLASSPATH, ".");
+ configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, getServletContextParam("struts.osgi.runLevel", "3"));
+
+ try {
+ felix = new Felix(configProps);
+ felix.init();
+ AutoProcessor.process(configProps, felix.getBundleContext());
+ felix.start();
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Apache Felix is running");
+ }
+ }
+ catch (Exception ex) {
+ throw new ConfigurationException("Couldn't start Apache Felix", ex);
+ }
+
+ addSpringOSGiSupport();
+
+ //add the bundle context to the ServletContext
+ servletContext.setAttribute(OSGI_BUNDLE_CONTEXT, felix.getBundleContext());
+ }
+
+ @Override
+ public void init(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ startFelix();
+ }
+
+ @Override
+ public Map getBundles() {
+ Map bundles = new HashMap();
+ for (Bundle bundle : felix.getBundleContext().getBundles()) {
+ bundles.put(bundle.getSymbolicName(), bundle);
+ }
+
+ return Collections.unmodifiableMap(bundles);
+ }
+
+ @Override
+ public Map getActiveBundles() {
+ Map bundles = new HashMap();
+ for (Bundle bundle : felix.getBundleContext().getBundles()) {
+ if (bundle.getState() == Bundle.ACTIVE) {
+ bundles.put(bundle.getSymbolicName(), bundle);
+ }
+ }
+ return Collections.unmodifiableMap(bundles);
+ }
+
+ @Override
+ public BundleContext getBundleContext() {
+ return felix.getBundleContext();
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ felix.stop();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Apache Felix has stopped");
+ }
+ }
+
+ @Override
+ protected void addSpringOSGiSupport() {
+ // see the javadoc for org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext for more details
+ // OsgiBundleXmlWebApplicationContext expects the the BundleContext to be set in the ServletContext under the attribute
+ // OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE
+ try {
+ Class clazz = Class.forName("org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext");
+ String key = (String) clazz.getDeclaredField("BUNDLE_CONTEXT_ATTRIBUTE").get(null);
+ servletContext.setAttribute(key, felix.getBundleContext());
+ } catch (ClassNotFoundException e) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Spring OSGi support is not enabled");
+ }
+ } catch (Exception e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error("The API of Spring OSGi has changed and the field [#0] is no longer available. The OSGi plugin needs to be updated", e,
+ "org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE");
+ }
+ }
+ }
+
+}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/GlassfishOSGiHost.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/GlassfishOSGiHost.java
new file mode 100644
index 000000000..1a500915a
--- /dev/null
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/GlassfishOSGiHost.java
@@ -0,0 +1,181 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.osgi.host;
+
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import org.apache.felix.shell.ShellService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleReference;
+
+import javax.servlet.ServletContext;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A glassfish implementation of an OsgiHost
+ */
+public class GlassfishOSGiHost extends BaseOsgiHost implements OsgiHost {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GlassfishOSGiHost.class);
+
+ /**
+ * Location inside the WAR where initial bundles are located.
+ */
+ private static final String BUNDLES_DIR = "/WEB-INF/classes/bundles/2/";
+
+ private BundleContext bctx = null;
+
+ @Override
+ public void init(ServletContext servletContext) {
+ this.servletContext = servletContext;
+
+ installManagedBundles();
+
+ addSpringOSGiSupport();
+
+ // add the bundle context to the ServletContext
+ servletContext.setAttribute(OSGI_BUNDLE_CONTEXT, bctx);
+ }
+
+ private void installManagedBundles() {
+ try {
+
+ // Obtaining BundleContext from ServletContext class which is loaded
+ // by bundle class loader
+ BundleReference ref = (BundleReference) servletContext.getClass()
+ .getClassLoader();
+ bctx = ref.getBundle().getBundleContext();
+
+ // installing managed bundles
+ installBundles();
+
+ } catch (Exception ex) {
+ LOG.error("Installing Managed Bundles met a problem", ex);
+ }
+ }
+
+ private void installBundles() throws Exception {
+ ArrayList installed = new ArrayList();
+ for (URL url : findBundles()) {
+ LOG.debug("Installing bundle [" + url + "]");
+ Bundle bundle = bctx.installBundle(url.toExternalForm());
+ installed.add(bundle);
+ }
+ for (Bundle bundle : installed) {
+ try {
+ bundle.start();
+ } catch (BundleException e) {
+ e.printStackTrace();
+ LOG.error("Failed to start " + bundle, e);
+ }
+ }
+
+ }
+
+ private List findBundles() throws Exception {
+ ArrayList list = new ArrayList();
+ for (Object o : this.servletContext.getResourcePaths(BUNDLES_DIR)) {
+ String name = (String) o;
+ if (name.endsWith(".jar")) {
+ URL url = this.servletContext.getResource(name);
+ if (url != null) {
+ list.add(url);
+ }
+ }
+ }
+
+ ProtectionDomain protectionDomain = ShellService.class.getProtectionDomain();
+ CodeSource codeSource = protectionDomain.getCodeSource();
+ URL loc = codeSource.getLocation();
+ list.add(loc);
+
+ return list;
+ }
+
+ @Override
+ protected void addSpringOSGiSupport() {
+ // see the javadoc for
+ // org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
+ // for more details
+ // OsgiBundleXmlWebApplicationContext expects the the BundleContext to
+ // be set in the ServletContext under the attribute
+ // OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE
+ try {
+ Class> clazz = Class
+ .forName("org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext");
+ String key = (String) clazz.getDeclaredField(
+ "BUNDLE_CONTEXT_ATTRIBUTE").get(null);
+ servletContext.setAttribute(key, bctx);
+ } catch (ClassNotFoundException e) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Spring OSGi support is not enabled");
+ }
+ } catch (Exception e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error(
+ "The API of Spring OSGi has changed and the field [#0] is no longer available. The OSGi plugin needs to be updated",
+ e,
+ "org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE");
+ }
+ }
+ }
+
+ /**
+ * This bundle map will not change, but the status of the bundles can change
+ * over time. Use getActiveBundles() for active bundles
+ */
+ @Override
+ public Map getBundles() {
+ Map bundles = new HashMap();
+ for (Bundle bundle : bctx.getBundles()) {
+ bundles.put(bundle.getSymbolicName(), bundle);
+ }
+
+ return Collections.unmodifiableMap(bundles);
+ }
+
+ public Map getActiveBundles() {
+ Map bundles = new HashMap();
+ for (Bundle bundle : bctx.getBundles()) {
+ if (bundle.getState() == Bundle.ACTIVE)
+ bundles.put(bundle.getSymbolicName(), bundle);
+ }
+
+ return Collections.unmodifiableMap(bundles);
+ }
+
+ public BundleContext getBundleContext() {
+ return bctx;
+ }
+
+ public void destroy() throws Exception {
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiHost.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/OsgiHost.java
similarity index 94%
rename from plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiHost.java
rename to plugins/osgi/src/main/java/org/apache/struts2/osgi/host/OsgiHost.java
index edda076c6..7c333c65e 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/OsgiHost.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/host/OsgiHost.java
@@ -19,7 +19,7 @@
* under the License.
*/
-package org.apache.struts2.osgi;
+package org.apache.struts2.osgi.host;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.Bundle;
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java
index 2ea2a7ab8..aec026a79 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java
@@ -27,5 +27,7 @@ import org.osgi.framework.BundleContext;
* the OsgiInterceptor must be applied to the action.
*/
public interface BundleContextAware {
+
void setBundleContext(BundleContext bundleContext);
+
}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java
index 7589498ed..4f6eed5ff 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java
@@ -20,28 +20,27 @@
*/
package org.apache.struts2.osgi.interceptor;
-import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
-import com.opensymphony.xwork2.inject.Inject;
-
-import javax.servlet.ServletContext;
-
-import org.apache.struts2.osgi.OsgiHost;
+import org.apache.struts2.osgi.host.OsgiHost;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
-import java.lang.reflect.Type;
+import javax.servlet.ServletContext;
import java.lang.reflect.ParameterizedType;
-import java.util.List;
+import java.lang.reflect.Type;
import java.util.ArrayList;
+import java.util.List;
/**
* If a class implements BundleContextAware, this interceptor will call the setBundleContext(BundleContext)
* method on it. If a class implements ServiceAware, this interceptor will call setService(List)
*/
public class OsgiInterceptor extends AbstractInterceptor {
+
private static final Logger LOG = LoggerFactory.getLogger(OsgiInterceptor.class);
private BundleContext bundleContext;
@@ -96,4 +95,5 @@ public class OsgiInterceptor extends AbstractInterceptor {
public void setServletContext(ServletContext servletContext) {
this.bundleContext = (BundleContext) servletContext.getAttribute(OsgiHost.OSGI_BUNDLE_CONTEXT);
}
+
}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java
index e7a549ea6..9c9fc7fb4 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java
@@ -28,5 +28,7 @@ import java.util.List;
* @param The type of the service
*/
public interface ServiceAware {
+
void setServices(List services);
+
}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/StaticContentBundleResourceLoader.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/StaticContentBundleResourceLoader.java
index 8cf11f58f..ef2827444 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/StaticContentBundleResourceLoader.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/StaticContentBundleResourceLoader.java
@@ -21,20 +21,19 @@
package org.apache.struts2.osgi.loaders;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
-import org.apache.struts2.osgi.DefaultBundleAccessor;
-import org.apache.struts2.osgi.BundleAccessor;
import com.opensymphony.xwork2.inject.Inject;
+import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
+import org.apache.struts2.osgi.BundleAccessor;
+
+import java.io.IOException;
+import java.net.URL;
/**
* Loads static resources from bundles
*
*/
public class StaticContentBundleResourceLoader extends DefaultStaticContentLoader {
+
private BundleAccessor bundleAccessor;
protected URL findResource(String path) throws IOException {
@@ -45,4 +44,5 @@ public class StaticContentBundleResourceLoader extends DefaultStaticContentLoade
public void setBundleAccessor(BundleAccessor bundleAccessor) {
this.bundleAccessor = bundleAccessor;
}
+
}
diff --git a/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/VelocityBundleResourceLoader.java b/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/VelocityBundleResourceLoader.java
index 20ddd5313..ae25ea19b 100644
--- a/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/VelocityBundleResourceLoader.java
+++ b/plugins/osgi/src/main/java/org/apache/struts2/osgi/loaders/VelocityBundleResourceLoader.java
@@ -48,4 +48,5 @@ public class VelocityBundleResourceLoader extends ClasspathResourceLoader {
throw new ResourceNotFoundException(e.getMessage());
}
}
+
}
diff --git a/plugins/osgi/src/test/java/org/apache/struts2/osgi/FelixOsgiHostTest.java b/plugins/osgi/src/test/java/org/apache/struts2/osgi/host/FelixOsgiHostTest.java
similarity index 54%
rename from plugins/osgi/src/test/java/org/apache/struts2/osgi/FelixOsgiHostTest.java
rename to plugins/osgi/src/test/java/org/apache/struts2/osgi/host/FelixOsgiHostTest.java
index 7024167ed..4cd584981 100644
--- a/plugins/osgi/src/test/java/org/apache/struts2/osgi/FelixOsgiHostTest.java
+++ b/plugins/osgi/src/test/java/org/apache/struts2/osgi/host/FelixOsgiHostTest.java
@@ -18,18 +18,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.struts2.osgi;
+package org.apache.struts2.osgi.host;
import junit.framework.TestCase;
+import org.apache.struts2.osgi.host.FelixOsgiHost;
public class FelixOsgiHostTest extends TestCase {
+
+ private FelixOsgiHost felixHost = new FelixOsgiHost();
+
public void testGetVersionFromString() {
- assertEquals("2.1.1", FelixOsgiHost.getVersionFromString("2.1.1-SNAPSHOT"));
- assertEquals("2.1.1", FelixOsgiHost.getVersionFromString("2.1.1.SNAPSHOT"));
- assertEquals("2.1.1", FelixOsgiHost.getVersionFromString("something-2.1.1.SNAPSHOT"));
- assertEquals("2.1.1", FelixOsgiHost.getVersionFromString("something-2-1-1.SNAPSHOT"));
- assertEquals("2.1.0", FelixOsgiHost.getVersionFromString("something-2-1.SNAPSHOT"));
- assertEquals("2.0.0", FelixOsgiHost.getVersionFromString("something-2.SNAPSHOT"));
- assertEquals("1.0.0", FelixOsgiHost.getVersionFromString("something"));
+ assertEquals("2.1.1", felixHost.getVersionFromString("2.1.1-SNAPSHOT"));
+ assertEquals("2.1.1", felixHost.getVersionFromString("2.1.1.SNAPSHOT"));
+ assertEquals("2.1.1", felixHost.getVersionFromString("something-2.1.1.SNAPSHOT"));
+ assertEquals("2.1.1", felixHost.getVersionFromString("something-2-1-1.SNAPSHOT"));
+ assertEquals("2.1.0", felixHost.getVersionFromString("something-2-1.SNAPSHOT"));
+ assertEquals("2.0.0", felixHost.getVersionFromString("something-2.SNAPSHOT"));
+ assertEquals("1.0.0", felixHost.getVersionFromString("something"));
}
+
}
diff --git a/plugins/osgi/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java b/plugins/osgi/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java
index 4cca06a41..d87a0f47b 100644
--- a/plugins/osgi/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java
+++ b/plugins/osgi/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java
@@ -1,7 +1,7 @@
package org.apache.struts2.osgi.interceptor;
import org.easymock.EasyMock;
-import org.apache.struts2.osgi.OsgiHost;
+import org.apache.struts2.osgi.host.OsgiHost;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
diff --git a/pom.xml b/pom.xml
index 8de360783..595112242 100644
--- a/pom.xml
+++ b/pom.xml
@@ -493,6 +493,16 @@
org.apache.felix
org.apache.felix.main
+ 4.0.3
+
+
+ org.apache.felix
+ org.apache.felix.shell
+ 1.4.3
+
+
+ org.apache.felix
+ org.apache.felix.shell.tui
1.4.1