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/06 02:36:32 UTC

svn commit: r762192 - in /struts/sandbox/trunk/struts2-osgi-plugin: admin-bundle/ plugin/src/main/java/org/apache/struts2/osgi/ plugin/src/main/resources/

Author: musachy
Date: Mon Apr  6 00:36:32 2009
New Revision: 762192

URL: http://svn.apache.org/viewvc?rev=762192&view=rev
Log:
Add support for the Convention plugin

Added:
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleClassLoaderInterface.java
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiUtil.java
      - copied, changed from r761957, struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/SpringOSGiUtil.java
Removed:
    struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/SpringOSGiUtil.java
Modified:
    struts/sandbox/trunk/struts2-osgi-plugin/admin-bundle/pom.xml
    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/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/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/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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -12,7 +12,7 @@
 		<dependency>
 			<groupId>org.apache.struts</groupId>
 			<artifactId>struts2-osgi-plugin</artifactId>
-			<version>1.0-SNAPSHOT</version>
+			<version>1.0.0-SNAPSHOT</version>
 		</dependency>
         <dependency>
             <groupId>junit</groupId>

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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -31,4 +31,5 @@
 
     ServiceReference getServiceReference(String className);
 
+    void addPackageFromBundle(Bundle bundle, String packageName);
 }

Added: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleClassLoaderInterface.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleClassLoaderInterface.java?rev=762192&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleClassLoaderInterface.java (added)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/BundleClassLoaderInterface.java Mon Apr  6 00:36:32 2009
@@ -0,0 +1,36 @@
+package org.apache.struts2.osgi;
+
+import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
+
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Collections;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * ClassLoaderInterface instance that delegates to the singleton of DefaultBundleAccessor 
+ */
+public class BundleClassLoaderInterface implements ClassLoaderInterface {
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+        return DefaultBundleAccessor.getInstance().loadClass(name);
+    }
+
+    public URL getResource(String name) {
+        return  DefaultBundleAccessor.getInstance().loadResource(name, true);
+    }
+
+    public Enumeration<URL> getResources(String name) throws IOException {
+        return Collections.enumeration(DefaultBundleAccessor.getInstance().loadResources(name, true));
+    }
+
+    public InputStream getResourceAsStream(String name) throws IOException {
+        return DefaultBundleAccessor.getInstance().loadResourceAsStream(name);
+    }
+
+    public ClassLoaderInterface getParent() {
+        return null;
+    }
+}

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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -9,8 +9,10 @@
 
 import com.opensymphony.xwork2.ObjectFactory;
 import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.inject.Inject;
 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.config.impl.DefaultConfiguration;
 import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
@@ -20,7 +22,7 @@
 
 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 {
         Configuration config = new DefaultConfiguration("struts.xml");
         ActionContext ctx = ActionContext.getContext();
@@ -43,8 +45,10 @@
         } finally {
             ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
         }
+
         List<PackageConfig> list = new ArrayList<PackageConfig>(config.getPackageConfigs().values());
         list.removeAll(pkgConfigs.values());
+        
         return list;
     }
     
@@ -79,7 +83,7 @@
 
                 //try to find a bean with that id
                 try {
-                    return SpringOSGiUtil.isValidBean(bundleContext, className);
+                    return OsgiUtil.isValidBean(bundleContext, className);
                 } catch (Exception e1) {
                     if (LOG.isDebugEnabled())
                         LOG.debug("Unable to find bean [#0]", className);

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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -3,6 +3,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.net.MalformedURLException;
 import java.util.*;
 import java.util.Map.Entry;
 
@@ -18,11 +19,14 @@
 import com.opensymphony.xwork2.ActionProxy;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
 
+/**
+ * Helper class that find resources and loads classes from the list of bundles
+ */
 public class DefaultBundleAccessor implements BundleAccessor {
 
     private static DefaultBundleAccessor self;
     private static final Logger LOG = LoggerFactory.getLogger(DefaultBundleAccessor.class);
-    
+
     private Map<String, Bundle> bundles = new HashMap<String, Bundle>();
     private BundleContext bundleContext;
     private Map<String, String> packageToBundle;
@@ -31,8 +35,7 @@
     public DefaultBundleAccessor() {
         self = this;
     }
-    
-    // todo: this is crap
+
     public static DefaultBundleAccessor getInstance() {
         return self;
     }
@@ -45,35 +48,54 @@
         return bundleContext.getServiceReference(className);
     }
 
-    public void init(Map<String,Bundle> bundles, BundleContext bundleContext, Map<String, String> packageToBundle) {
+    public void init(Map<String, Bundle> bundles, BundleContext bundleContext, Map<String, String> packageToBundle) {
         this.bundles = Collections.unmodifiableMap(bundles);
         this.bundleContext = bundleContext;
-        this.packageToBundle = Collections.unmodifiableMap(packageToBundle);
+        this.packageToBundle = packageToBundle;
         this.packagesByBundle = new HashMap<Bundle, Set<String>>();
-        for (Map.Entry<String,String> entry : packageToBundle.entrySet()) {
+        for (Map.Entry<String, String> entry : packageToBundle.entrySet()) {
             Bundle bundle = bundles.get(entry.getValue());
-            Set<String> pkgs = packagesByBundle.get(bundle);
-            if (pkgs == null) {
-                pkgs = new HashSet<String>();
-                packagesByBundle.put(bundle, pkgs);
-            }
-            pkgs.add(entry.getKey());
+            addPackageFromBundle(bundle, entry.getKey());
+        }
+    }
+
+    /**
+     *  Add as Bundle -> Package mapping 
+     * @param bundle the bundle where the package was loaded from
+     * @param packageName the anme of the loaded package
+     */
+    public void addPackageFromBundle(Bundle bundle, String packageName) {
+        this.packageToBundle.put(packageName, bundle.getSymbolicName());
+        Set<String> pkgs = packagesByBundle.get(bundle);
+        if (pkgs == null) {
+            pkgs = new HashSet<String>();
+            packagesByBundle.put(bundle, pkgs);
         }
-        this.packagesByBundle = Collections.unmodifiableMap(packagesByBundle);
+        pkgs.add(packageName);
     }
-    
+
     public Class<?> loadClass(String className) throws ClassNotFoundException {
         Class cls = null;
+
         Bundle bundle = getCurrentBundle();
         if (bundle != null) {
             cls = bundle.loadClass(className);
             LOG.debug("Located class [#0] in bundle [#1]", className, bundle.getSymbolicName());
         }
 
+        //try all the bundles
+        for (Bundle bundle2 : bundles.values()) {
+            try {
+                return bundle2.loadClass(className);
+            } catch (Exception ex) {
+                //ignore
+            }
+        }
+
         if (cls == null) {
             //try to find a bean with that id (hack for spring that searches all bundles)
             try {
-                Object bean = SpringOSGiUtil.getBean(bundleContext, className);
+                Object bean = OsgiUtil.getBean(bundleContext, className);
                 if (bean != null)
                     cls = bean.getClass();
             } catch (Exception e) {
@@ -81,9 +103,9 @@
                     LOG.debug("Unable to find bean [#0]", className);
             }
         }
-        
+
         if (cls == null) {
-            throw new ClassNotFoundException("Unable to find class "+className+" in bundles");
+            throw new ClassNotFoundException("Unable to find class " + className + " in bundles");
         }
         return cls;
     }
@@ -104,12 +126,16 @@
     }
 
     public List<URL> loadResources(String name) throws IOException {
+        return loadResources(name, false);
+    }
+
+    public List<URL> loadResources(String name, boolean translate) throws IOException {
         Bundle bundle = getCurrentBundle();
         if (bundle != null) {
             List<URL> resources = new ArrayList<URL>();
             Enumeration e = bundle.getResources(name);
             while (e.hasMoreElements()) {
-                resources.add((URL) e.nextElement());
+                resources.add(translate ? OsgiUtil.translateBundleURLToJarURL((URL) e.nextElement(), getCurrentBundle()) : (URL) e.nextElement());
             }
             return resources;
         }
@@ -137,10 +163,24 @@
     }
 
     public URL loadResource(String name) {
+        return loadResource(name, false);
+    }
+
+    public URL loadResource(String name, boolean translate) {
         Bundle bundle = getCurrentBundle();
         if (bundle != null) {
-            return bundle.getResource(name);
+            URL url = bundle.getResource(name);
+            try {
+                return translate ? OsgiUtil.translateBundleURLToJarURL(url, getCurrentBundle()) : url;
+            } catch (Exception e) {
+                if (LOG.isErrorEnabled()) {
+                    LOG.error("Unable to translate bunfle URL to jar URL", e);
+                }
+
+                return null;
+            }
         }
+
         return null;
     }
 
@@ -154,7 +194,7 @@
 
     public InputStream loadResourceAsStream(String name) throws IOException {
         URL url = loadResource(name);
-        if (url != null) { 
+        if (url != null) {
             return url.openStream();
         }
         return null;

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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -72,6 +72,7 @@
     private List<? extends BundleActivator> extraBundleActivators;
     private boolean cleanBundleCache;
     private static Pattern versionPattern = Pattern.compile("([\\d])+[\\.-]");
+    private String startRunLevel;
 
     protected void startFelix() {
         //load properties from felix embedded file
@@ -107,7 +108,7 @@
         configProps.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false");
         configProps.put(FelixConstants.LOG_LEVEL_PROP, "4");
         configProps.put(FelixConstants.BUNDLE_CLASSPATH, ".");
-        configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, "2");        
+        configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, startRunLevel);        
 
         try {
             List<BundleActivator> list = new ArrayList<BundleActivator>();
@@ -210,7 +211,7 @@
      */
     private void addExportedPackages(Properties strutsConfigProps, Properties configProps) {
         String[] rootPackages = StringUtils.split((String) strutsConfigProps.get("scanning.package.includes"), ",");
-        ResourceFinder finder = new ResourceFinder(StringUtils.EMPTY, OsgiConfigurationProvider.class.getClassLoader());
+        ResourceFinder finder = new ResourceFinder(StringUtils.EMPTY);
         List<String> exportedPackages = new ArrayList<String>();
         //build a list of subpackages
         for (String rootPackage : rootPackages) {
@@ -327,4 +328,9 @@
     public void setCleanBundleCache(String cleanBundleCache) {
         this.cleanBundleCache = "true".equalsIgnoreCase(cleanBundleCache);
     }
+
+    @Inject("struts.osgi.startRunLevel")
+    public void setStartRunLevel(String startRunLevel) {
+        this.startRunLevel = startRunLevel;
+    }
 }

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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -1,22 +1,27 @@
 package org.apache.struts2.osgi;
 
 import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.ActionContext;
 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.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 java.util.Arrays;
 import java.util.HashMap;
@@ -24,6 +29,8 @@
 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
@@ -90,9 +97,59 @@
             }
         }
         bundleAccessor.init(osgiHost.getBundles(), bundleContext, packageToBundle);
+
+        //reload container that will load configuration based on bundles (like convention plugin)
+        reloadExtraProviders(configuration.getContainer());
+
         bundlesChanged = false;
     }
 
+    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);
+
+        //init action context
+        ActionContext ctx = ActionContext.getContext();
+        if (ctx == null) {
+            ctx = new ActionContext(new HashMap());
+            ActionContext.setContext(ctx);
+        }
+
+        //reload all providers by bundle
+        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());
+                    for (PackageProvider provider : providers) {
+                        if (LOG.isDebugEnabled())
+                            LOG.debug("Reloading provider [#0] for bundle [#1]", provider.getClass().getName(), bundle.getSymbolicName());
+                        //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);
+            }
+        }
+    }
+
     public synchronized boolean needsReload() {
         return bundlesChanged;
     }

Copied: struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiUtil.java (from r761957, struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/SpringOSGiUtil.java)
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiUtil.java?p2=struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiUtil.java&p1=struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/SpringOSGiUtil.java&r1=761957&r2=762192&rev=762192&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/SpringOSGiUtil.java (original)
+++ struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/java/org/apache/struts2/osgi/OsgiUtil.java Mon Apr  6 00:36:32 2009
@@ -2,31 +2,54 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.MalformedURLException;
 
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Bundle;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+public class OsgiUtil {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiUtil.class);
 
-public class SpringOSGiUtil {
     public static boolean isValidBean(BundleContext bundleContext, String beanId) throws InvalidSyntaxException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         return getBean(bundleContext, beanId) != null;
     }
-    
+
     public static Object getBean(BundleContext bundleContext, String beanId) throws InvalidSyntaxException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         ServiceReference[] references = bundleContext.getAllServiceReferences(
-            "org.springframework.context.ApplicationContext", null);
+                "org.springframework.context.ApplicationContext", null);
         if (references != null && references.length > 0) {
             Object beanFactory = bundleContext.getService(references[0]);
             //this class and the BeanFactory service are loaded by different classloaders
             //so we cannot cast to a common interface (is there any other (nice) way of doing this?)
             return getBean(beanFactory, beanId);
         }
-        
+
         return null;
     }
-    
+
     private static Object getBean(Object beanFactory, String beanId) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
         Method getBeanMethod = beanFactory.getClass().getMethod("getBean", String.class);
         return getBeanMethod.invoke(beanFactory, beanId);
     }
+
+    /**
+     * A bundle is a jar, and a bunble URL will be useless to clients, this method translates
+     * a URL to a resource inside a bundle from "bundle:something/path" to "jar:file:bundlelocation!/path"
+     */
+    public static URL translateBundleURLToJarURL(URL bundleUrl, Bundle bundle) throws MalformedURLException {
+        if (bundleUrl != null && "bundle".equalsIgnoreCase(bundleUrl.getProtocol())) {
+            StringBuilder sb = new StringBuilder("jar:");
+            sb.append(bundle.getLocation());
+            sb.append("!");
+            sb.append(bundleUrl.getFile());
+            return new URL(sb.toString());
+        }
+
+        return bundleUrl;
+    }
 }

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=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -8,8 +8,9 @@
 
 import com.opensymphony.xwork2.ObjectFactory;
 import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.PackageProvider;
 import com.opensymphony.xwork2.config.entities.PackageConfig;
 
 public interface PackageLoader {
-    List<PackageConfig> loadPackages(Bundle bundle, BundleContext bundleContext, ObjectFactory objectFactory, Map<String,PackageConfig> map) throws ConfigurationException;
+    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/resources/struts-plugin.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/plugin/src/main/resources/struts-plugin.xml?rev=762192&r1=762191&r2=762192&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  6 00:36:32 2009
@@ -10,11 +10,15 @@
     <bean name="osgi" type="com.opensymphony.xwork2.ObjectFactory" class="org.apache.struts2.osgi.DelegatingObjectFactory" />
     <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" />
     
     <constant name="struts.objectFactory" value="osgi" />
     <constant name="struts.objectFactory.delegate" value="struts" />
     <constant name="struts.freemarker.manager.classname" value="org.apache.struts2.osgi.BundleFreemarkerManager" />
     <constant name="struts.staticContentLoader" value="org.apache.struts2.osgi.loaders.StaticContentBundleResourceLoader" />
 
+    <constant name="struts.convention.action.includeJars" value="jar:file:.*?/bundles/.*?\.jar(!/)?" />
+
     <constant name="struts.osgi.clearBundleCache" value="true" />
+    <constant name="struts.osgi.startRunLevel" value="2" />
 </struts>