You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mu...@apache.org on 2009/04/12 07:26:27 UTC
svn commit: r764282 - in /struts/sandbox/trunk/struts2-osgi-plugin:
demo-bundle/ demo-bundle/src/main/java/actions/osgi/
demo-bundle/src/main/resources/
demo-bundle/src/main/resources/content/osgi/ plugin/
plugin/src/main/java/org/apache/struts2/osgi/ ...
Author: musachy
Date: Sun Apr 12 05:26:26 2009
New Revision: 764282
URL: http://svn.apache.org/viewvc?rev=764282&view=rev
Log:
Refactor Felix start up into a listener (now there is full support for Spring IoC). Remove activator
Added:
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/beanRefContext.xml
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/test/java/org/apache/struts2/osgi/interceptor/
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java
Removed:
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/StrutsActivator.java
Modified:
struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/pom.xml
struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/java/actions/osgi/HelloWorldAction.java
struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.ftl
struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.vm
struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/struts.xml
struts/sandbox/trunk/struts2-osgi-plugin/plugin/pom.xml
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiHost.java
struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/struts-plugin.xml
Modified: struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/pom.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/pom.xml?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/pom.xml (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/pom.xml Sun Apr 12 05:26:26 2009
@@ -39,6 +39,12 @@
<version>2.1.7-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.struts</groupId>
+ <artifactId>struts2-osgi-plugin</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
@@ -56,15 +62,9 @@
<configuration>
<instructions>
<manifestLocation>META-INF</manifestLocation>
- <Import-Package>
- *,com.opensymphony.xwork2
- </Import-Package>
- <Bundle-Activator>
- org.apache.struts2.osgi.StrutsActivator
- </Bundle-Activator>
- <Spring-Context>
- *;create-asynchronously:=false
- </Spring-Context>
+ <Import-Package>*,com.opensymphony.xwork2</Import-Package>
+ <Spring-Context>*;create-asynchronously:=false</Spring-Context>
+ <Struts2-Enabled>true</Struts2-Enabled>
</instructions>
</configuration>
</plugin>
Modified: struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/java/actions/osgi/HelloWorldAction.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/java/actions/osgi/HelloWorldAction.java?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/java/actions/osgi/HelloWorldAction.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/java/actions/osgi/HelloWorldAction.java Sun Apr 12 05:26:26 2009
@@ -1,13 +1,19 @@
package actions.osgi;
import com.opensymphony.xwork2.ActionSupport;
-import org.apache.struts2.convention.annotation.ParentPackage;
-import org.apache.struts2.convention.annotation.ResultPath;
import org.apache.struts2.convention.annotation.Action;
+import org.apache.struts2.convention.annotation.ResultPath;
+import org.apache.struts2.osgi.interceptor.BundleContextAware;
+import org.apache.struts2.osgi.interceptor.ServiceAware;
+import org.osgi.framework.BundleContext;
+import org.springframework.context.ApplicationContext;
+
+import java.util.List;
@ResultPath("/content")
-public class HelloWorldAction extends ActionSupport {
+public class HelloWorldAction extends ActionSupport implements BundleContextAware, ServiceAware<ApplicationContext> {
private Message message;
+ private BundleContext bundleContext;
@Action("hello-convention")
public String execute() {
@@ -32,4 +38,12 @@
sb.append("}");
return sb.toString();
}
+
+ public void setBundleContext(BundleContext context) {
+ this.bundleContext = context;
+ }
+
+ public void setServices(List<ApplicationContext> service) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
}
\ No newline at end of file
Modified: struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.ftl
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.ftl?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.ftl (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.ftl Sun Apr 12 05:26:26 2009
@@ -3,7 +3,7 @@
<title>Action mapped by the XML configurationn</title>
</head>
<body>
- This is an action mapped by XML configuration, using a FreeMarker result.
+ This is an action mapped by XML configuration, using a <b>FreeMarker</b> result.
<br />
Message from Action: ${message.text}
</body>
Modified: struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.vm
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.vm?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.vm (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/content/osgi/hello.vm Sun Apr 12 05:26:26 2009
@@ -3,8 +3,7 @@
<title>Action mapped by the XML configurationn</title>
</head>
<body>
- This is an action mapped by XML configuration, using a Velocity result.
- ->$top
+ This is an action mapped by XML configuration, using a <b>Velocity</b> result.
<br />
Message from Action: $message.text
</body>
Modified: struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/struts.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/struts.xml?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/struts.xml (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/demo-bundle/src/main/resources/struts.xml Sun Apr 12 05:26:26 2009
@@ -4,7 +4,7 @@
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
- <package name="bundle-demo" namespace="/osgi" extends="struts-default">
+ <package name="bundle-demo" namespace="/osgi" extends="osgi-default">
<default-action-ref name="home" />
<action name="hello-velocity" class="helloWorldAction">
<result type="velocity">/content/osgi/hello.vm</result>
Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/pom.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/pom.xml?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/pom.xml (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/pom.xml Sun Apr 12 05:26:26 2009
@@ -84,5 +84,12 @@
<scope>test</scope>
<version>3.8.1</version>
</dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ <version>2.4</version>
+ </dependency>
</dependencies>
</project>
Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/FelixOsgiHost.java Sun Apr 12 05:26:26 2009
@@ -38,6 +38,9 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.Constants;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.BundleEvent;
import org.osgi.util.tracker.ServiceTracker;
import javax.servlet.ServletContext;
@@ -63,17 +66,13 @@
* Apache felix implementation of an OsgiHost
* See http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html
*/
-public class FelixOsgiHost implements OsgiHost {
+public class FelixOsgiHost implements OsgiHost, BundleListener {
private static final Logger LOG = LoggerFactory.getLogger(FelixOsgiHost.class);
private Felix felix;
private Map<String, Bundle> bundles = Collections.synchronizedMap(new HashMap<String, Bundle>());
- private List<? extends BundleActivator> extraBundleActivators;
- private boolean cleanBundleCache;
private static Pattern versionPattern = Pattern.compile("([\\d])+[\\.-]");
- private String startRunLevel;
private ServletContext servletContext;
- private String logLevel;
protected void startFelix() {
//load properties from felix embedded file
@@ -96,7 +95,8 @@
if (LOG.isDebugEnabled())
LOG.debug("Storing bundle at [#0]", storageDir);
- if (cleanBundleCache) {
+ String cleanBundleCache = getServletContextParam("struts.osgi.cleanBundleCache", "true");
+ if ("true".equalsIgnoreCase(cleanBundleCache)) {
if (LOG.isDebugEnabled())
LOG.debug("Clearing bundle cache");
configProps.put(FelixConstants.FRAMEWORK_STORAGE_CLEAN, FelixConstants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
@@ -104,15 +104,24 @@
//other properties
configProps.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false");
- configProps.put(FelixConstants.LOG_LEVEL_PROP, logLevel);
+ configProps.put(FelixConstants.LOG_LEVEL_PROP, getServletContextParam("struts.osgi.logLevel", "1"));
configProps.put(FelixConstants.BUNDLE_CLASSPATH, ".");
- configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, startRunLevel);
+ configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, getServletContextParam("struts.osgi.runLevel", "3"));
try {
List<BundleActivator> list = new ArrayList<BundleActivator>();
- if (extraBundleActivators != null)
- list.addAll(extraBundleActivators);
list.add(new AutoActivator(configProps));
+
+ //this activator just hooks this class as a BundleListener
+ list.add(new BundleActivator() {
+ public void start(BundleContext bundleContext) throws Exception {
+ bundleContext.addBundleListener(FelixOsgiHost.this);
+ }
+
+ public void stop(BundleContext bundleContext) throws Exception {
+ }
+ });
+
configProps.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
felix = new Felix(configProps);
@@ -121,19 +130,23 @@
LOG.trace("Apache Felix is running");
}
catch (Exception ex) {
- throw new ConfigurationException("Couldn't start Felix (OSGi)", ex);
- }
-
- // Wait for all bundles to load
- while (bundles.size() < bundlePaths) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- LOG.error("An error occured while waiting for bundle activation", e);
- }
+ 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 int addAutoStartBundles(Properties configProps) {
@@ -329,19 +342,12 @@
}
}
- /**
- * Bundle activators that will be added to the container
- */
- public void setExtraBundleActivators(List<? extends BundleActivator> extraBundleActivators) {
- this.extraBundleActivators = extraBundleActivators;
- }
-
public Map<String, Bundle> getBundles() {
return Collections.unmodifiableMap(bundles);
}
- public void addBundle(Bundle bundle) {
- bundles.put(bundle.getSymbolicName(), bundle);
+ public BundleContext getBundleContext() {
+ return felix.getBundleContext();
}
public void destroy() throws Exception {
@@ -352,28 +358,18 @@
}
}
- @Override
- public void init() throws Exception {
- startFelix();
- }
-
- @Inject("struts.osgi.clearBundleCache")
- public void setCleanBundleCache(String cleanBundleCache) {
- this.cleanBundleCache = "true".equalsIgnoreCase(cleanBundleCache);
- }
-
- @Inject("struts.osgi.startRunLevel")
- public void setStartRunLevel(String startRunLevel) {
- this.startRunLevel = startRunLevel;
- }
-
- @Inject
- public void setServletContext(ServletContext servletContext) {
+ public void init(ServletContext servletContext) throws Exception {
this.servletContext = servletContext;
+ startFelix();
}
- @Inject("struts.osgi.logLevel")
- public void setLogLevel(String logLevel) {
- this.logLevel = logLevel;
+ /**
+ * Listen to BundleEvent(s) and build a bundles list
+ */
+ public void bundleChanged(BundleEvent evt) {
+ Bundle bundle = evt.getBundle();
+ if (evt.getType() == BundleEvent.STARTED && bundle.getSymbolicName() != null) {
+ this.bundles.put(bundle.getSymbolicName(), bundle);
+ }
}
}
Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java Sun Apr 12 05:26:26 2009
@@ -21,87 +21,58 @@
package org.apache.struts2.osgi;
-import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.PackageProvider;
import com.opensymphony.xwork2.config.entities.PackageConfig;
-import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
-import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import org.apache.struts2.osgi.loaders.VelocityBundleResourceLoader;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.velocity.app.Velocity;
-import org.apache.commons.lang.xwork.StringUtils;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
-import java.util.Arrays;
+import javax.servlet.ServletContext;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
-import java.util.List;
-import java.util.ArrayList;
/**
* Struts package provider that starts the OSGi container and deelgates package loading
*/
public class OsgiConfigurationProvider implements PackageProvider {
+ private static final String STRUTS_ENABLED = "Struts2-Enabled";
private static final Logger LOG = LoggerFactory.getLogger(OsgiConfigurationProvider.class);
private Configuration configuration;
private ObjectFactory objectFactory;
- private OsgiHost osgiHost;
+ private OsgiHost osgiHost;
private BundleContext bundleContext;
private BundleAccessor bundleAccessor;
private boolean bundlesChanged = false;
-
- public void destroy() {
- try {
- if (LOG.isTraceEnabled())
- LOG.trace("Stopping OSGi container");
- osgiHost.destroy();
- } catch (Exception e) {
- LOG.error("Failed to stop OSGi container", e);
- }
- }
+ private ServletContext servletContext;
public void init(Configuration configuration) throws ConfigurationException {
- if (LOG.isTraceEnabled())
- LOG.trace("Starting OSGi container");
- try {
- osgiHost.setExtraBundleActivators(Arrays.asList(new BundleRegistrationListener()));
- osgiHost.init();
- bundleAccessor.setBundles(osgiHost.getBundles());
- } catch (Exception e) {
- if (LOG.isErrorEnabled())
- LOG.error("Failed to start the OSGi container", e);
- throw new ConfigurationException(e);
- }
+ osgiHost = (OsgiHost) servletContext.getAttribute(StrutsOsgiListener.OSGI_HOST);
+ bundleContext = osgiHost.getBundleContext();
+ bundleAccessor.setBundles(osgiHost.getBundles());
+ bundleAccessor.setBundleContext(bundleContext);
this.configuration = configuration;
}
public synchronized void loadPackages() throws ConfigurationException {
- ServiceReference[] refs;
- try {
- refs = bundleContext.getServiceReferences(PackageLoader.class.getName(), null);
- } catch (InvalidSyntaxException e) {
- throw new ConfigurationException(e);
- }
-
-
//init action contect
ActionContext ctx = ActionContext.getContext();
if (ctx == null) {
@@ -111,26 +82,20 @@
Map<String, String> packageToBundle = new HashMap<String, String>();
Set<String> bundleNames = new HashSet<String>();
-
- if (refs != null) {
- for (ServiceReference ref : refs) {
- String bundleName = ref.getBundle().getSymbolicName();
- if (!bundleNames.contains(bundleName)) {
- bundleNames.add(bundleName);
-
- if (LOG.isDebugEnabled())
- LOG.debug("Loading packages from bundle [#0]", bundleName);
-
- PackageLoader loader = (PackageLoader) bundleContext.getService(ref);
- try {
- ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, bundleName);
- for (PackageConfig pkg : loader.loadPackages(ref.getBundle(), bundleContext, objectFactory, configuration.getPackageConfigs())) {
- configuration.addPackageConfig(pkg.getName(), pkg);
- packageToBundle.put(pkg.getName(), bundleName);
- }
- } finally {
- ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
- }
+
+ //iterate over the bundles and load packages from them
+ for (Bundle bundle : osgiHost.getBundles().values()) {
+ String bundleName = bundle.getSymbolicName();
+ if (shouldProcessBundle(bundle) && !bundleNames.contains(bundleName)) {
+ bundleNames.add(bundleName);
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("Loading packages from bundle [#0]", bundleName);
+
+ PackageLoader loader = new BundlePackageLoader();
+ for (PackageConfig pkg : loader.loadPackages(bundle, bundleContext, objectFactory, configuration.getPackageConfigs())) {
+ configuration.addPackageConfig(pkg.getName(), pkg);
+ packageToBundle.put(pkg.getName(), bundleName);
}
}
}
@@ -138,7 +103,7 @@
//add the loaded packages to the BundleAccessor
bundleAccessor.setPackageToBundle(packageToBundle);
- //reload container that will load configuration based on bundles (like convention plugin)
+ //reload container, that will load configuration based on bundles (like convention plugin)
reloadExtraProviders(configuration.getContainer());
bundlesChanged = false;
@@ -151,26 +116,22 @@
if (conventionPackageProvider != null)
providers.add(conventionPackageProvider);
- //init action context
- ActionContext ctx = ActionContext.getContext();
- if (ctx == null) {
- ctx = new ActionContext(new HashMap());
- ActionContext.setContext(ctx);
- }
-
//reload all providers by bundle
+ ActionContext ctx = ActionContext.getContext();
for (Bundle bundle : osgiHost.getBundles().values()) {
- try {
- //the Convention plugin will use BundleClassLoaderInterface from the ActionContext to find resources
- //and load classes
- ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, new BundleClassLoaderInterface());
- ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, bundle.getSymbolicName());
-
- Object bundleActivator = bundle.getHeaders().get("Bundle-Activator");
- if (bundleActivator != null && StringUtils.equals(StrutsActivator.class.getName(), bundleActivator.toString())) { ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, bundle.getSymbolicName());
+ String bundleName = bundle.getSymbolicName();
+ if (shouldProcessBundle(bundle)) {
+ try {
+ //the Convention plugin will use BundleClassLoaderInterface from the ActionContext to find resources
+ //and load classes
+ ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, new BundleClassLoaderInterface());
+ ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, bundleName);
+
for (PackageProvider provider : providers) {
- if (LOG.isDebugEnabled())
- LOG.debug("Reloading provider [#0] for bundle [#1]", provider.getClass().getName(), bundle.getSymbolicName());
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Reloading provider [#0] for bundle [#1]", provider.getClass().getName(), bundleName);
+ }
+
//get the existing packages before reloading the provider (se we can figure out what are the new packages)
Set<String> packagesBeforeLoading = new HashSet(configuration.getPackageConfigNames());
provider.loadPackages();
@@ -182,14 +143,23 @@
bundleAccessor.addPackageFromBundle(bundle, packageName);
}
}
+ } finally {
+ ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
+ ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, null);
}
- } finally {
- ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
- ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, null);
}
}
}
+ /**
+ * Checks for "Struts2-Enabled" header in the bundle
+ */
+ protected boolean shouldProcessBundle(Bundle bundle) {
+ String strutsEnabled = (String) bundle.getHeaders().get(STRUTS_ENABLED);
+
+ return "true".equalsIgnoreCase(strutsEnabled);
+ }
+
public synchronized boolean needsReload() {
return bundlesChanged;
}
@@ -218,28 +188,18 @@
vm.setVelocityProperties(props);
}
- /**
- * Listens to bundle events and adds bundles to the bundle list when one is activated
- */
- class BundleRegistrationListener implements BundleActivator, BundleListener {
- public void start(BundleContext context) throws Exception {
- context.addBundleListener(this);
- bundleContext = context;
- bundleAccessor.setBundleContext(bundleContext);
- }
-
- public void stop(BundleContext ctx) throws Exception {
- }
-
- public void bundleChanged(BundleEvent evt) {
- if (evt.getType() == BundleEvent.STARTED && evt.getBundle().getSymbolicName() != null) {
- if (LOG.isDebugEnabled())
- LOG.debug("Started bundle [#0]", evt.getBundle().getSymbolicName());
+ @Inject
+ public void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
- osgiHost.addBundle(evt.getBundle());
- bundlesChanged = true;
- }
+ public void destroy() {
+ try {
+ if (LOG.isTraceEnabled())
+ LOG.trace("Stopping OSGi container");
+ osgiHost.destroy();
+ } catch (Exception e) {
+ LOG.error("Failed to stop OSGi container", e);
}
}
-
}
Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiHost.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiHost.java?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiHost.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiHost.java Sun Apr 12 05:26:26 2009
@@ -23,14 +23,21 @@
import org.osgi.framework.BundleActivator;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import javax.servlet.ServletContext;
import java.util.List;
import java.util.Map;
+/**
+ * Implementations of this class start an OSGi container. They must also add the BundleContext to
+ * the ServletContext under the key OsgiHost.OSGI_BUNDLE_CONTEXT;
+ */
public interface OsgiHost {
+ String OSGI_BUNDLE_CONTEXT = "__struts_osgi_bundle_context";
+
void destroy() throws Exception;
- void init() throws Exception;
- void setExtraBundleActivators(List<? extends BundleActivator> extraBundleActivators);
+ void init(ServletContext servletContext) throws Exception;
Map<String, Bundle> getBundles();
- void addBundle(Bundle bundle);
+ BundleContext getBundleContext();
}
Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java?rev=764282&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/StrutsOsgiListener.java Sun Apr 12 05:26:26 2009
@@ -0,0 +1,34 @@
+package org.apache.struts2.osgi;
+
+import org.apache.struts2.StrutsException;
+
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContext;
+
+/**
+ * ServletContextListener that starts Apache Felix
+ */
+public class StrutsOsgiListener implements ServletContextListener {
+ public static final String OSGI_HOST = "__struts_osgi_host";
+ private FelixOsgiHost osgiHost;
+
+ public void contextInitialized(ServletContextEvent sce) {
+ ServletContext servletContext = sce.getServletContext();
+ osgiHost = new FelixOsgiHost();
+ servletContext.setAttribute(OSGI_HOST, osgiHost);
+ try {
+ osgiHost.init(servletContext);
+ } catch (Exception e) {
+ throw new StrutsException("Apache Felix failed to start", e);
+ }
+ }
+
+ public void contextDestroyed(ServletContextEvent sce) {
+ try {
+ osgiHost.destroy();
+ } catch (Exception e) {
+ throw new StrutsException("Apache Felix failed to stop", e);
+ }
+ }
+}
Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java?rev=764282&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java Sun Apr 12 05:26:26 2009
@@ -0,0 +1,11 @@
+package org.apache.struts2.osgi.interceptor;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * Action implementing this interface will receive an instance of the BundleContext,
+ * the OsgiInterceptor must be applied to the action.
+ */
+public interface BundleContextAware {
+ void setBundleContext(BundleContext bundleContext);
+}
Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java?rev=764282&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java Sun Apr 12 05:26:26 2009
@@ -0,0 +1,79 @@
+package org.apache.struts2.osgi.interceptor;
+
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import com.opensymphony.xwork2.ActionInvocation;
+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.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+import java.lang.reflect.Type;
+import java.lang.reflect.ParameterizedType;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * If a class implements BundleContextAware, this interceptor will call the setBundleContext(BundleContext)
+ * method on it
+ */
+public class OsgiInterceptor extends AbstractInterceptor {
+ private static final Logger LOG = LoggerFactory.getLogger(OsgiInterceptor.class);
+
+ private BundleContext bundleContext;
+
+ public String intercept(ActionInvocation invocation) throws Exception {
+ if (bundleContext != null) {
+ Object action = invocation.getAction();
+
+ //inject BundleContext
+ if (action instanceof BundleContextAware)
+ ((BundleContextAware)action).setBundleContext(bundleContext);
+
+ //inject service implementations
+ if (action instanceof ServiceAware) {
+ Type[] types = action.getClass().getGenericInterfaces();
+ if (types != null) {
+ for (Type type : types) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ if (parameterizedType.getRawType() instanceof Class) {
+ Class clazz = (Class) parameterizedType.getRawType();
+ if (ServiceAware.class.equals(clazz)) {
+ Class serviceClass = (Class) parameterizedType.getActualTypeArguments()[0];
+ ServiceReference[] refs = bundleContext.getAllServiceReferences(serviceClass.getName(), null);
+ //get the services
+ if (refs != null) {
+ List services = new ArrayList(refs.length);
+ for (ServiceReference ref : refs) {
+ Object service = bundleContext.getService(ref);
+ //wow, that's a lot of nested ifs
+ if (service != null)
+ services.add(service);
+ }
+
+ if (!services.isEmpty())
+ ((ServiceAware)action).setServices(services);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (LOG.isWarnEnabled()){
+ LOG.warn("The OSGi interceptor was not able to find the BundleContext in the ServletContext");
+ }
+
+ return invocation.invoke();
+ }
+
+ @Inject
+ public void setServletContext(ServletContext servletContext) {
+ this.bundleContext = (BundleContext) servletContext.getAttribute(OsgiHost.OSGI_BUNDLE_CONTEXT);
+ }
+}
Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java?rev=764282&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java Sun Apr 12 05:26:26 2009
@@ -0,0 +1,7 @@
+package org.apache.struts2.osgi.interceptor;
+
+import java.util.List;
+
+public interface ServiceAware<T> {
+ void setServices(List<T> service);
+}
Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/beanRefContext.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/beanRefContext.xml?rev=764282&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/beanRefContext.xml (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/beanRefContext.xml Sun Apr 12 05:26:26 2009
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<beans>
+ <bean id="parent-context-bean" class="org.springframework.context.support.ClassPathXmlApplicationContext">
+ <constructor-arg>
+ <list>
+ <value>classpath*:applicationContext.xml</value>
+ </list>
+ </constructor-arg>
+ </bean>
+</beans>
Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/struts-plugin.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/struts-plugin.xml?rev=764282&r1=764281&r2=764282&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/struts-plugin.xml (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/struts-plugin.xml Sun Apr 12 05:26:26 2009
@@ -12,12 +12,6 @@
<constant name="struts.convention.action.includeJars" value="jar:file:.*?/bundles/.*?\.jar(!/)?" />
- <constant name="struts.osgi.clearBundleCache" value="true" />
- <constant name="struts.osgi.startRunLevel" value="3" />
-
- <!--1 = error, 2 = warning, 3 = information, and 4 = debug -->
- <constant name="struts.osgi.logLevel" value="1" />
-
<bean type="org.apache.struts2.osgi.BundleAccessor" class="org.apache.struts2.osgi.DefaultBundleAccessor" />
<bean type="org.apache.struts2.osgi.PackageLoader" class="org.apache.struts2.osgi.BundlePackageLoader" />
<bean name="osgi" type="com.opensymphony.xwork2.ObjectFactory" class="org.apache.struts2.osgi.DelegatingObjectFactory" />
@@ -25,4 +19,17 @@
<bean name="osgi" type="com.opensymphony.xwork2.config.PackageProvider" class="org.apache.struts2.osgi.OsgiConfigurationProvider" />
<bean name="felix" type="org.apache.struts2.osgi.OsgiHost" class="org.apache.struts2.osgi.FelixOsgiHost" />
<bean name="osgi" type="com.opensymphony.xwork2.util.finder.ClassLoaderInterface" class="org.apache.struts2.osgi.BundleClassLoaderInterface" />
+
+ <package name="osgi-default" extends="struts-default" abstract="yes">
+ <interceptors>
+ <interceptor name="osgi" class="org.apache.struts2.osgi.interceptor.OsgiInterceptor" />
+
+ <interceptor-stack name="osgiStack">
+ <interceptor-ref name="defaultStack"/>
+ <interceptor-ref name="osgi"/>
+ </interceptor-stack>
+ </interceptors>
+
+ <default-interceptor-ref name="osgiStack"/>
+ </package>
</struts>
Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java?rev=764282&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/test/java/org/apache/struts2/osgi/interceptor/OsgiInterceptorTest.java Sun Apr 12 05:26:26 2009
@@ -0,0 +1,53 @@
+package org.apache.struts2.osgi.interceptor;
+
+import org.easymock.EasyMock;
+import org.apache.struts2.osgi.OsgiHost;
+import org.osgi.framework.BundleContext;
+
+import javax.servlet.ServletContext;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import junit.framework.TestCase;
+
+public class OsgiInterceptorTest extends TestCase {
+ public void testBundleContextAware() throws Exception {
+ ServletContext servletContext = EasyMock.createStrictMock(ServletContext.class);
+ BundleContext bundleContext = EasyMock.createStrictMock(BundleContext.class);
+ ActionInvocation actionInvocation = EasyMock.createStrictMock(ActionInvocation.class);
+ BundleContextAware bundleContextAware = EasyMock.createStrictMock(BundleContextAware.class);
+
+ EasyMock.expect(servletContext.getAttribute(OsgiHost.OSGI_BUNDLE_CONTEXT)).andReturn(bundleContext);
+ EasyMock.expect(actionInvocation.getAction()).andReturn(bundleContextAware);
+ bundleContextAware.setBundleContext(bundleContext);
+ EasyMock.expect(actionInvocation.invoke()).andReturn("");
+
+ EasyMock.replay(bundleContextAware);
+ EasyMock.replay(servletContext);
+ EasyMock.replay(actionInvocation);
+
+ OsgiInterceptor osgiInterceptor = new OsgiInterceptor();
+ osgiInterceptor.setServletContext(servletContext);
+ osgiInterceptor.intercept(actionInvocation);
+
+ EasyMock.verify(bundleContextAware);
+ }
+
+ public void testBundleContextAwareNegative() throws Exception {
+ ServletContext servletContext = EasyMock.createStrictMock(ServletContext.class);
+ ActionInvocation actionInvocation = EasyMock.createStrictMock(ActionInvocation.class);
+ BundleContextAware bundleContextAware = EasyMock.createStrictMock(BundleContextAware.class);
+
+ EasyMock.expect(servletContext.getAttribute(OsgiHost.OSGI_BUNDLE_CONTEXT)).andReturn(null);
+ EasyMock.expect(actionInvocation.invoke()).andReturn("");
+
+ EasyMock.replay(bundleContextAware);
+ EasyMock.replay(servletContext);
+ EasyMock.replay(actionInvocation);
+
+ OsgiInterceptor osgiInterceptor = new OsgiInterceptor();
+ osgiInterceptor.setServletContext(servletContext);
+ osgiInterceptor.intercept(actionInvocation);
+
+ EasyMock.verify(bundleContextAware);
+ }
+}