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/13 03:55:03 UTC

svn commit: r764348 - in /struts/sandbox/trunk/struts2-osgi-plugin: admin-bundle/ admin-bundle/src/main/java/org/apache/struts2/osgi/admin/actions/ plugin/src/main/java/org/apache/struts2/osgi/ plugin/src/main/java/org/apache/struts2/osgi/interceptor/ ...

Author: musachy
Date: Mon Apr 13 01:55:02 2009
New Revision: 764348

URL: http://svn.apache.org/viewvc?rev=764348&view=rev
Log:
Add support for loading/unloading configuration when bundles are started/stopped

Modified:
    struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/pom.xml
    struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/src/main/java/org/apache/struts2/osgi/admin/actions/BundlesAction.java
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleFreemarkerManager.java
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java
    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/PackageLoader.java
    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/struts-plugin.xml

Modified: struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/pom.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/pom.xml?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/pom.xml (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/pom.xml Mon Apr 13 01:55:02 2009
@@ -14,6 +14,12 @@
             <artifactId>struts2-osgi-plugin</artifactId>
             <version>1.0.0-SNAPSHOT</version>
         </dependency>
+       <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
@@ -36,21 +42,26 @@
                 <configuration>
                     <instructions>
                         <manifestLocation>META-INF</manifestLocation>
-                        <Import-Package>
-                            *,com.opensymphony.xwork2
-                        </Import-Package>
-                        <Export-Package>
-                            org.apache.struts2.osgi.admin*
-                        </Export-Package>
-                        <Bundle-Activator>
-                            org.apache.struts2.osgi.StrutsActivator
-                        </Bundle-Activator>
-                        <Spring-Context>
-                            *;create-asynchronously:=false
-                        </Spring-Context>
+                        <Struts2-Enabled>true</Struts2-Enabled>
+                        <Import-Package>*,com.opensymphony.xwork2</Import-Package>
+                        <Export-Package>org.apache.struts2.osgi.admin*</Export-Package>
+                        <Spring-Context>*;create-asynchronously:=false</Spring-Context>
                     </instructions>
                 </configuration>
             </plugin>
+            <plugin>
+                <inherited>true</inherited>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
         <pluginManagement>
             <plugins>
@@ -64,5 +75,4 @@
             </plugins>
         </pluginManagement>
     </build>
-
 </project>

Modified: struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/src/main/java/org/apache/struts2/osgi/admin/actions/BundlesAction.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/src/main/java/org/apache/struts2/osgi/admin/actions/BundlesAction.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/src/main/java/org/apache/struts2/osgi/admin/actions/BundlesAction.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/src/main/java/org/apache/struts2/osgi/admin/actions/BundlesAction.java Mon Apr 13 01:55:02 2009
@@ -21,23 +21,24 @@
 
 package org.apache.struts2.osgi.admin.actions;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.struts2.dispatcher.DefaultActionSupport;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.entities.PackageConfig;
+import com.opensymphony.xwork2.inject.Inject;
 import org.apache.struts2.osgi.BundleAccessor;
-import org.apache.struts2.osgi.DefaultBundleAccessor;
 import org.apache.struts2.osgi.OsgiHost;
+import org.apache.struts2.osgi.StrutsOsgiListener;
+import org.apache.struts2.util.ServletContextAware;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 
-import com.opensymphony.xwork2.config.Configuration;
-import com.opensymphony.xwork2.config.entities.PackageConfig;
-import com.opensymphony.xwork2.inject.Inject;
+import javax.servlet.ServletContext;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
 
-public class BundlesAction extends DefaultActionSupport {
+public class BundlesAction extends ActionSupport implements ServletContextAware {
 
     private String id;
 
@@ -46,7 +47,6 @@
     private OsgiHost osgiHost;
 
     public BundlesAction() {
-         this.bundleAccessor = DefaultBundleAccessor.getInstance();
     }
 
     public String index() {
@@ -61,6 +61,11 @@
         Bundle bundle = osgiHost.getBundles().get(id);
         try {
             bundle.start();
+
+            //start fires the BundleEvent.STARTED, which load the config
+            //we need to wait until the config is loaded from that bundle
+            //there no easy way/elegant way to know if the bundle is being processed
+            Thread.sleep(1000);
         } catch (Exception e) {
             addActionError(e.toString());
         }
@@ -105,8 +110,12 @@
     public List<PackageConfig> getPackages() {
         List<PackageConfig> pkgs = new ArrayList<PackageConfig>();
         Bundle bundle = getBundle();
-        for (String name : bundleAccessor.getPackagesByBundle(bundle)) {
-            pkgs.add(configuration.getPackageConfig(name));
+        if (bundle.getState() == Bundle.ACTIVE) {
+            for (String name : bundleAccessor.getPackagesByBundle(bundle)) {
+                PackageConfig packageConfig = configuration.getPackageConfig(name);
+                if (packageConfig != null)
+                    pkgs.add(packageConfig);
+            }
         }
         return pkgs;
     }
@@ -161,7 +170,11 @@
     }
 
     @Inject
-    public void setOsgiHost(OsgiHost osgiHost) {
-        this.osgiHost = osgiHost;
+    public void setBundleAccessor(BundleAccessor bundleAccessor) {
+        this.bundleAccessor = bundleAccessor;
+    }
+
+    public void setServletContext(ServletContext servletContext) {
+        osgiHost = (OsgiHost) servletContext.getAttribute(StrutsOsgiListener.OSGI_HOST);
     }
 }

Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java Mon Apr 13 01:55:02 2009
@@ -36,8 +36,6 @@
 
     String CURRENT_BUNDLE_NAME = "__bundle_name__";
 
-    void setPackageToBundle(Map<String, String> packageToBundle);
-
     Class loadClass(String name) throws ClassNotFoundException;
 
     InputStream loadResourceAsStream(String name) throws IOException;

Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleFreemarkerManager.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleFreemarkerManager.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleFreemarkerManager.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleFreemarkerManager.java Mon Apr 13 01:55:02 2009
@@ -44,7 +44,7 @@
  */
 public class BundleFreemarkerManager extends FreemarkerManager {
     private static final Logger LOG = LoggerFactory.getLogger(BundleFreemarkerManager.class);
-    
+
     @Override
     protected TemplateLoader getTemplateLoader(ServletContext servletContext) {
         // construct a FileTemplateLoader for the init-param 'TemplatePath'
@@ -59,7 +59,8 @@
             try {
                 templatePathLoader = new FileTemplateLoader(new File(templatePath));
             } catch (IOException e) {
-                LOG.error("Invalid template path specified: #1",e, e.getMessage());
+                if (LOG.isErrorEnabled())
+                    LOG.error("Invalid template path specified: [#0]", e, e.getMessage());
             }
         }
 
@@ -73,10 +74,10 @@
                         new FreeMarkerBundleResourceLoader()
                 })
                 : new MultiTemplateLoader(new TemplateLoader[]{
-                    new WebappTemplateLoader(servletContext),
-                    new StrutsClassTemplateLoader(),
-                    new FreeMarkerBundleResourceLoader()
-                });
+                new WebappTemplateLoader(servletContext),
+                new StrutsClassTemplateLoader(),
+                new FreeMarkerBundleResourceLoader()
+        });
     }
-    
+
 }

Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java Mon Apr 13 01:55:02 2009
@@ -41,48 +41,41 @@
 import com.opensymphony.xwork2.util.logging.Logger;
 import com.opensymphony.xwork2.util.logging.LoggerFactory;
 
+/**
+ * Package loader implementation that loads resources from a bundle
+ */
 public class BundlePackageLoader implements PackageLoader {
     private static final Logger LOG = LoggerFactory.getLogger(BundlePackageLoader.class);
 
-    public List<PackageConfig> loadPackages(Bundle bundle, BundleContext bundleContext, ObjectFactory objectFactory, Map<String,PackageConfig> pkgConfigs) throws ConfigurationException {
+    public List<PackageConfig> loadPackages(Bundle bundle, BundleContext bundleContext, ObjectFactory objectFactory, Map<String, PackageConfig> pkgConfigs) throws ConfigurationException {
         Configuration config = new DefaultConfiguration("struts.xml");
-        ActionContext ctx = ActionContext.getContext();
-        if (ctx == null) {
-            ctx = new ActionContext(new HashMap());
-            ActionContext.setContext(ctx);
-        }
-
-        try {
-            // Ensure all requested classes and resources will be resolved using the current bundle
-            ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, bundle.getSymbolicName());
-
-            BundleConfigurationProvider prov = new BundleConfigurationProvider("struts.xml", bundle, bundleContext);
-            for (PackageConfig pkg : pkgConfigs.values()) {
-                config.addPackageConfig(pkg.getName(), pkg);
-            }
-            prov.setObjectFactory(objectFactory);
-            prov.init(config);
-            prov.loadPackages();
-        } finally {
-            ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
-        }
+        BundleConfigurationProvider prov = new BundleConfigurationProvider("struts.xml", bundle, bundleContext);
+        for (PackageConfig pkg : pkgConfigs.values()) {
+            config.addPackageConfig(pkg.getName(), pkg);
+        }
+        prov.setObjectFactory(objectFactory);
+        prov.init(config);
+        prov.loadPackages();
 
         List<PackageConfig> list = new ArrayList<PackageConfig>(config.getPackageConfigs().values());
         list.removeAll(pkgConfigs.values());
-        
+
         return list;
     }
-    
+
     static class BundleConfigurationProvider extends XmlConfigurationProvider {
         private Bundle bundle;
         private BundleContext bundleContext;
 
-        public BundleConfigurationProvider(String filename, Bundle bundle, BundleContext bundleContext) { 
+        public BundleConfigurationProvider(String filename, Bundle bundle, BundleContext bundleContext) {
             super(filename, false);
             this.bundle = bundle;
             this.bundleContext = bundleContext;
         }
-        public BundleConfigurationProvider(String filename) { super(filename); }
+
+        public BundleConfigurationProvider(String filename) {
+            super(filename);
+        }
 
         @Override
         protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
@@ -90,23 +83,25 @@
             return e.hasMoreElements() ? new EnumeratorIterator<URL>(e) : null;
         }
     }
-    
+
     static class EnumeratorIterator<E> implements Iterator<E> {
         Enumeration<E> e = null;
+
         public EnumeratorIterator(Enumeration<E> e) {
             this.e = e;
         }
+
         public boolean hasNext() {
-          return e.hasMoreElements();
+            return e.hasMoreElements();
         }
 
         public E next() {
-          return e.nextElement();
+            return e.nextElement();
         }
 
         public void remove() {
-          throw new UnsupportedOperationException();
+            throw new UnsupportedOperationException();
         }
-      }
+    }
 
 }

Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java Mon Apr 13 01:55:02 2009
@@ -50,8 +50,8 @@
     private static final Logger LOG = LoggerFactory.getLogger(DefaultBundleAccessor.class);
 
     private BundleContext bundleContext;
-    private Map<String, String> packageToBundle;
-    private Map<Bundle, Set<String>> packagesByBundle;
+    private Map<String, String> packageToBundle = new HashMap<String, String>();
+    private Map<Bundle, Set<String>> packagesByBundle = new HashMap<Bundle, Set<String>>();
     private OsgiHost osgiHost;
 
     public DefaultBundleAccessor() {
@@ -88,15 +88,6 @@
         return bundleContext != null ? bundleContext.getServiceReferences(className, params) : null;
     }
 
-    public void setPackageToBundle(Map<String, String> packageToBundle) {
-        this.packageToBundle = packageToBundle;
-        this.packagesByBundle = new HashMap<Bundle, Set<String>>();
-        for (Map.Entry<String, String> entry : packageToBundle.entrySet()) {
-            Bundle bundle = osgiHost.getActiveBundles().get(entry.getValue());
-            addPackageFromBundle(bundle, entry.getKey());
-        }
-    }
-
     /**
      *  Add as Bundle -> Package mapping 
      * @param bundle the bundle where the package was loaded from
@@ -117,7 +108,7 @@
         if (bundle != null) {
             Class cls = bundle.loadClass(className);
             if (LOG.isTraceEnabled())
-                LOG.debug("Located class [#0] in bundle [#1]", className, bundle.getSymbolicName());
+                LOG.trace("Located class [#0] in bundle [#1]", className, bundle.getSymbolicName());
             return cls;
         }
 

Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java Mon Apr 13 01:55:02 2009
@@ -61,7 +61,10 @@
         try {
             return delegateObjectFactory.buildBean(className, extraContext, injectInternal);
         } catch (Exception e) {
-            return bundleResourceLoader.loadClass(className).newInstance();
+            Object object = bundleResourceLoader.loadClass(className).newInstance();
+            if (injectInternal)
+                injectInternalBeans(object);
+            return object;
         }
     }
 

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=764348&r1=764347&r2=764348&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 Mon Apr 13 01:55:02 2009
@@ -71,11 +71,10 @@
  * <p>struts.osgi.logLevel: Defaults to "1". Felix log level. 1 = error, 2 = warning, 3 = information, and 4 = debug </p>
  * <p>struts.osgi.runLevel: Defaults to "3". Run level to start the container.</p>
  */
-public class FelixOsgiHost implements OsgiHost, BundleListener {
+public class FelixOsgiHost implements OsgiHost {
     private static final Logger LOG = LoggerFactory.getLogger(FelixOsgiHost.class);
 
     private Felix felix;
-    private Map<String, Bundle> bundles = Collections.synchronizedMap(new HashMap<String, Bundle>());
     private static final Pattern versionPattern = Pattern.compile("([\\d])+[\\.-]");
     private ServletContext servletContext;
 
@@ -98,7 +97,7 @@
         String storageDir = System.getProperty("java.io.tmpdir") + ".felix-cache";
         configProps.setProperty(Constants.FRAMEWORK_STORAGE, storageDir);
         if (LOG.isDebugEnabled())
-            LOG.debug("Storing bundle at [#0]", storageDir);
+            LOG.debug("Storing bundles at [#0]", storageDir);
 
         String cleanBundleCache = getServletContextParam("struts.osgi.clearBundleCache", "true");
         if ("true".equalsIgnoreCase(cleanBundleCache)) {
@@ -116,17 +115,6 @@
         try {
             List<BundleActivator> list = new ArrayList<BundleActivator>();
             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);
@@ -145,8 +133,9 @@
     }
 
     /**
-     * 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
+     * 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
      */
@@ -352,17 +341,22 @@
      * Use getActiveBundles() for active bundles
      */
     public Map<String, Bundle> getBundles() {
+        Map<String, Bundle> bundles = new HashMap<String, Bundle>();
+        for (Bundle bundle : felix.getBundleContext().getBundles()) {
+            bundles.put(bundle.getSymbolicName(), bundle);
+        }
+
         return Collections.unmodifiableMap(bundles);
     }
 
     public Map<String, Bundle> getActiveBundles() {
-        Map<String, Bundle> activeBundleMap = new HashMap<String, Bundle>();
-        for (Map.Entry<String, Bundle> entry : bundles.entrySet()) {
-            if (entry.getValue().getState() == Bundle.ACTIVE)
-                activeBundleMap.put(entry.getKey(), entry.getValue());
+        Map<String, Bundle> bundles = new HashMap<String, Bundle>();
+        for (Bundle bundle : felix.getBundleContext().getBundles()) {
+            if (bundle.getState() == Bundle.ACTIVE)
+                bundles.put(bundle.getSymbolicName(), bundle);
         }
 
-        return activeBundleMap;
+        return Collections.unmodifiableMap(bundles);
     }
 
     public BundleContext getBundleContext() {
@@ -370,30 +364,13 @@
     }
 
     public void destroy() throws Exception {
-        try {
-            felix.stop();
-        } finally {
-            bundles = null;
-        }
+        felix.stop();
+        if (LOG.isTraceEnabled())
+            LOG.trace("Apache Felix has stopped");
     }
 
     public void init(ServletContext servletContext) {
         this.servletContext = servletContext;
         startFelix();
     }
-
-    /**
-     * Listen to BundleEvent(s) and build a bundles list
-     */
-    public void bundleChanged(BundleEvent evt) {
-        Bundle bundle = evt.getBundle();
-        String bundleName = bundle.getSymbolicName();
-        if (bundleName != null) {
-            switch (evt.getType()) {
-                case BundleEvent.STARTED:
-                    this.bundles.put(bundleName, bundle);
-                    break;
-            }
-        }
-    }
 }

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=764348&r1=764347&r2=764348&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 Mon Apr 13 01:55:02 2009
@@ -35,8 +35,11 @@
 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.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.BundleEvent;
 
 import javax.servlet.ServletContext;
 import java.util.ArrayList;
@@ -50,7 +53,7 @@
 /**
  * Struts package provider that starts the OSGi container and deelgates package loading
  */
-public class OsgiConfigurationProvider implements PackageProvider {
+public class OsgiConfigurationProvider implements PackageProvider, BundleListener {
 
     private static final String STRUTS_ENABLED = "Struts2-Enabled";
     private static final Logger LOG = LoggerFactory.getLogger(OsgiConfigurationProvider.class);
@@ -68,13 +71,14 @@
         osgiHost = (OsgiHost) servletContext.getAttribute(StrutsOsgiListener.OSGI_HOST);
         bundleContext = osgiHost.getBundleContext();
         bundleAccessor.setBundleContext(bundleContext);
-        // I can't figure out why BundleAccessor doesn't get the OsgiHost injected
-        //for reason it always gets a new instace...weird
         bundleAccessor.setOsgiHost(osgiHost);
         this.configuration = configuration;
     }
 
     public synchronized void loadPackages() throws ConfigurationException {
+        if (LOG.isTraceEnabled())
+            LOG.trace("Loading packages from XML and Convention on startup");                
+
         //init action contect
         ActionContext ctx = ActionContext.getContext();
         if (ctx == null) {
@@ -82,7 +86,6 @@
             ActionContext.setContext(ctx);
         }
 
-        Map<String, String> packageToBundle = new HashMap<String, String>();
         Set<String> bundleNames = new HashSet<String>();
 
         //iterate over the bundles and load packages from them
@@ -90,66 +93,74 @@
             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);
-                }
+                //load XML and COnvention config
+                loadConfigFromBundle(bundle);
             }
         }
 
-        //add the loaded packages to the BundleAccessor
-        bundleAccessor.setPackageToBundle(packageToBundle);
-
-        //reload container, that will load configuration based on bundles (like convention plugin)
-        reloadExtraProviders(configuration.getContainer());
-
         bundlesChanged = false;
+        bundleContext.addBundleListener(this);
     }
 
-    protected void reloadExtraProviders(Container container) {
-        //these providers will be reloaded for each bundle
-        List<PackageProvider> providers = new ArrayList<PackageProvider>();
-        PackageProvider conventionPackageProvider = container.getInstance(PackageProvider.class, "convention.packageProvider");
-        if (conventionPackageProvider != null)
-            providers.add(conventionPackageProvider);
+    /**
+     * Loads XML config as well as Convention config from a bundle
+     * Limitation: Constants and Beans are ignored on XML config
+     */
+    protected void loadConfigFromBundle(Bundle bundle) {
+        String bundleName = bundle.getSymbolicName();
+        if (LOG.isDebugEnabled())
+            LOG.debug("Loading packages from bundle [#0]", bundleName);
 
-        //reload all providers by bundle
+        //init action context
         ActionContext ctx = ActionContext.getContext();
-        for (Bundle bundle : osgiHost.getBundles().values()) {
-            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(), 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();
-                        Set<String> packagesAfterLoading = new HashSet(configuration.getPackageConfigNames());
-                        packagesAfterLoading.removeAll(packagesBeforeLoading);
-                        if (!packagesAfterLoading.isEmpty()) {
-                            //add the new packages to the map of bundle -> package
-                            for (String packageName : packagesAfterLoading)
-                                bundleAccessor.addPackageFromBundle(bundle, packageName);
-                        }
-                    }
-                } finally {
-                    ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
-                    ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, null);
-                }
+        if (ctx == null) {
+            ctx = new ActionContext(new HashMap());
+            ActionContext.setContext(ctx);
+        }
+
+        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);
+
+            if (LOG.isTraceEnabled())
+                LOG.trace("Loading XML config from bundle [#0]", bundleName);
+
+            //XML config
+            PackageLoader loader = new BundlePackageLoader();
+            for (PackageConfig pkg : loader.loadPackages(bundle, bundleContext, objectFactory, configuration.getPackageConfigs())) {
+                configuration.addPackageConfig(pkg.getName(), pkg);
+                bundleAccessor.addPackageFromBundle(bundle, pkg.getName());
+            }
+
+            //Convention
+            //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());
+
+            PackageProvider conventionPackageProvider = configuration.getContainer().getInstance(PackageProvider.class, "convention.packageProvider");
+            if (conventionPackageProvider != null) {
+                if (LOG.isTraceEnabled())
+                    LOG.trace("Loading Convention config from bundle [#0]", bundleName);
+                conventionPackageProvider.loadPackages();
             }
+
+            Set<String> packagesAfterLoading = new HashSet(configuration.getPackageConfigNames());
+            packagesAfterLoading.removeAll(packagesBeforeLoading);
+            if (!packagesAfterLoading.isEmpty()) {
+                //add the new packages to the map of bundle -> package
+                for (String packageName : packagesAfterLoading)
+                    bundleAccessor.addPackageFromBundle(bundle, packageName);
+            }
+
+            if (this.configuration.getRuntimeConfiguration() != null) {
+                //if there is a runtime config, it meas that this method was called froma bundle start event
+                //instead of the initial load, in that case, reload the config
+                this.configuration.rebuildRuntimeConfiguration();
+            }
+        } finally {
+            ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
+            ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, null);
         }
     }
 
@@ -171,11 +182,6 @@
         this.objectFactory = factory;
     }
 
-    @Inject("felix")
-    public void setOsgiHost(OsgiHost osgiHost) {
-        this.osgiHost = osgiHost;
-    }
-
     @Inject
     public void setBundleAccessor(BundleAccessor acc) {
         this.bundleAccessor = acc;
@@ -197,11 +203,45 @@
 
     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);
+            if (LOG.isErrorEnabled())
+                LOG.error("Failed to stop OSGi container", e);
+        }
+    }
+
+    /**
+     * Listens to bundle event to load/unload config
+     */
+    public void bundleChanged(BundleEvent bundleEvent) {
+        Bundle bundle = bundleEvent.getBundle();
+        String bundleName = bundle.getSymbolicName();
+        if (bundleName != null && shouldProcessBundle(bundle)) {
+            switch (bundleEvent.getType()) {
+                case BundleEvent.STARTED:
+                    if (LOG.isTraceEnabled())
+                        LOG.trace("The bundlde [#0] has been activated and will be scanned for struts configuration", bundleName);
+                    loadConfigFromBundle(bundle);
+                    break;
+                case BundleEvent.STOPPED:
+                    onBundleStopped(bundle);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * This method is called when a bundle is stopped, so the config that is related to it is removed
+     *
+     * @param bundle the bundle that stopped
+     */
+    protected void onBundleStopped(Bundle bundle) {
+        Set<String> packages = bundleAccessor.getPackagesByBundle(bundle);
+        if (!packages.isEmpty()) {
+            if (LOG.isTraceEnabled())
+                LOG.trace("The bundle [#0] has been stopped. The packages [#1] will be disabled", bundle.getSymbolicName(), StringUtils.join(packages, ","));
+            for (String packageName : packages)
+                configuration.removePackageConfig(packageName);
         }
     }
 }

Modified: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java?rev=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java Mon Apr 13 01:55:02 2009
@@ -32,6 +32,9 @@
 import com.opensymphony.xwork2.config.PackageProvider;
 import com.opensymphony.xwork2.config.entities.PackageConfig;
 
+/**
+ * Implementations of this interface can load packages from a Bundle
+ */
 public interface PackageLoader {
     List<PackageConfig> loadPackages(Bundle bundle, BundleContext bundleContext, ObjectFactory objectFactory, Map<String, PackageConfig> map) throws ConfigurationException;
 }

Modified: 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=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/BundleContextAware.java Mon Apr 13 01:55:02 2009
@@ -1,3 +1,23 @@
+/*
+ * $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.interceptor;
 
 import org.osgi.framework.BundleContext;

Modified: 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=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/OsgiInterceptor.java Mon Apr 13 01:55:02 2009
@@ -1,3 +1,23 @@
+/*
+ * $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.interceptor;
 
 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

Modified: 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=764348&r1=764347&r2=764348&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/interceptor/ServiceAware.java Mon Apr 13 01:55:02 2009
@@ -1,3 +1,23 @@
+/*
+ * $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.interceptor;
 
 import java.util.List;

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=764348&r1=764347&r2=764348&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 Mon Apr 13 01:55:02 2009
@@ -14,10 +14,10 @@
 
     <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" />
     <bean name="springOsgi" type="com.opensymphony.xwork2.ObjectFactory" class="org.apache.struts2.osgi.SpringOsgiObjectFactory" />
     <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">