Author: mrdon Date: Sun Jul 29 06:45:02 2007 New Revision: 560720 URL: http://svn.apache.org/viewvc?view=rev&rev=560720 Log: initial import
Added: struts/sandbox/trunk/struts2-osgi-plugin/ struts/sandbox/trunk/struts2-osgi-plugin/pom.xml struts/sandbox/trunk/struts2-osgi-plugin/src/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleResourceLoader.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/StrutsActivator.java struts/sandbox/trunk/struts2-osgi-plugin/src/main/resources/ struts/sandbox/trunk/struts2-osgi-plugin/src/main/resources/struts-plugin.xml Added: struts/sandbox/trunk/struts2-osgi-plugin/pom.xml URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/pom.xml?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/pom.xml (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/pom.xml Sun Jul 29 06:45:02 2007 @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-plugins</artifactId> + <version>2.0.9</version> + </parent> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-osgi-plugin</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + <name>Struts 2 OSGI Plugin</name> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-osgi-plugin/</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-osgi-plugin/</developerConnection> + <url>http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/struts2-osgi-plugin/</url> + </scm> + + <dependencies> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.main</artifactId> + <version>0.9.0-incubator-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-core</artifactId> + <version>2.0.9</version> + </dependency> + + <dependency> + <groupId>velocity-tools</groupId> + <artifactId>velocity-tools</artifactId> + <version>1.1</version> + </dependency> + + + <dependency> + <groupId>velocity</groupId> + <artifactId>velocity</artifactId> + <version>1.4</version> + </dependency> + <dependency> + <groupId>velocity</groupId> + <artifactId>velocity-dep</artifactId> + <version>1.4</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + <version>3.8.1</version> + </dependency> + </dependencies> +</project> Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleAccessor.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,17 @@ +package org.apache.struts2.osgi; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Map; + +import org.osgi.framework.Bundle; + +public interface BundleAccessor { + + void setBundles(Map<String,Bundle> bundles); + Class loadClass(String name) throws ClassNotFoundException; + InputStream loadResourceAsStream(String name) throws IOException; + URL loadResource(String name); + +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundlePackageLoader.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,84 @@ +package org.apache.struts2.osgi; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.osgi.framework.Bundle; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.entities.PackageConfig; +import com.opensymphony.xwork2.config.impl.DefaultConfiguration; +import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; +import com.opensymphony.xwork2.util.location.Location; + +public class BundlePackageLoader implements PackageLoader { + + public List<PackageConfig> loadPackages(Bundle bundle, ObjectFactory objectFactory, Map<String,PackageConfig> pkgConfigs) throws ConfigurationException { + BundleConfigurationProvider prov = new BundleConfigurationProvider("struts.xml", bundle); + Configuration config = new DefaultConfiguration("struts.xml"); + for (PackageConfig pkg : pkgConfigs.values()) { + config.addPackageConfig(pkg.getName(), pkg); + } + prov.setObjectFactory(objectFactory); + prov.init(config); + prov.loadPackages(); + return new ArrayList<PackageConfig>(config.getPackageConfigs().values()); + } + + static class BundleConfigurationProvider extends XmlConfigurationProvider { + private Bundle bundle; + + public BundleConfigurationProvider(String filename, Bundle bundle) { + super(filename, true); + this.bundle = bundle; + } + public BundleConfigurationProvider(String filename) { super(filename); } + + @Override + protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException { + Enumeration<URL> e = bundle.getResources("struts.xml"); + Iterator<URL> iter = new EnumeratorIterator<URL>(e); + return iter; + } + @Override + protected boolean verifyAction(String className, String name, + Location loc) { + try { + Class cls = bundle.loadClass(className); + return cls != null; + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + } + + + } + + 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(); + } + + public E next() { + return e.nextElement(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleResourceLoader.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleResourceLoader.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleResourceLoader.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/BundleResourceLoader.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,30 @@ +package org.apache.struts2.osgi; + +import java.io.InputStream; + +import org.apache.struts2.util.ClassLoaderUtils; +import org.apache.struts2.views.velocity.StrutsResourceLoader; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; + +import com.opensymphony.xwork2.inject.Inject; + +public class BundleResourceLoader extends ClasspathResourceLoader { + + public synchronized InputStream getResourceStream(String name) + throws ResourceNotFoundException { + if ((name == null) || (name.length() == 0)) { + throw new ResourceNotFoundException("No template name provided"); + } + + if (name.startsWith("/")) { + name = name.substring(1); + } + + try { + return DefaultBundleAccessor.getInstance().loadResourceAsStream(name); + } catch (Exception e) { + throw new ResourceNotFoundException(e.getMessage()); + } + } +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DefaultBundleAccessor.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,93 @@ +package org.apache.struts2.osgi; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.framework.Bundle; + +public class DefaultBundleAccessor implements BundleAccessor { + + private static DefaultBundleAccessor self; + private static final Log LOG = LogFactory.getLog(DefaultBundleAccessor.class); + + private Map<String, Bundle> bundles = new HashMap<String, Bundle>(); + private Map<String,String> classToBundle = new HashMap<String,String>(); + + public DefaultBundleAccessor() { + self = this; + } + + // todo: this is crap + public static DefaultBundleAccessor getInstance() { + return self; + } + + public void setBundles(Map<String,Bundle> bundles) { + this.bundles = bundles; + classToBundle.clear(); + } + + public Class<?> loadClass(String name) throws ClassNotFoundException { + Class cls = null; + if (classToBundle.containsKey(name)) { + bundles.get(classToBundle.get(name)).loadClass(name); + } else { + for (Entry<String,Bundle> entry : bundles.entrySet()) { + try { + cls = entry.getValue().loadClass(name); + if (cls != null) { + classToBundle.put(name, entry.getKey()); + } + } catch (ClassNotFoundException ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("class not found in bundle "+entry.getValue().getSymbolicName(), ex); + } + } + } + } + + if (cls == null) { + throw new ClassNotFoundException("Unable to find class "+name+" in bundles"); + } + return cls; + } + + public List<URL> loadResources(String name) throws IOException { + List<URL> resources = new ArrayList<URL>(); + for (Entry<String,Bundle> entry : bundles.entrySet()) { + Enumeration e = entry.getValue().getResources(name); + while (e.hasMoreElements()) { + resources.add((URL) e.nextElement()); + } + } + return resources; + } + + public URL loadResource(String name) { + URL url = null; + for (Entry<String,Bundle> entry : bundles.entrySet()) { + url = entry.getValue().getResource(name); + if (url != null) + break; + } + return url; + } + + public InputStream loadResourceAsStream(String name) throws IOException { + URL url = loadResource(name); + if (url != null) { + return url.openStream(); + } + return null; + } + +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/DelegatingObjectFactory.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,40 @@ +package org.apache.struts2.osgi; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.Inject; + +public class DelegatingObjectFactory extends ObjectFactory { + private ObjectFactory delegateObjectFactory; + private BundleAccessor bundleResourceLoader; + + @Inject + public DelegatingObjectFactory(@Inject Container container, + @Inject("struts.objectFactory.delegate") String delegate) { + + if (delegate == null) { + delegate = "struts"; + } + delegateObjectFactory = container.getInstance(ObjectFactory.class, delegate); + } + + @Inject + public void setBundleResourceLoader(BundleAccessor rl) { + this.bundleResourceLoader = rl; + } + + + @Override + public Class getClassInstance(String className) throws ClassNotFoundException { + try + { + return delegateObjectFactory.getClassInstance(className); + } + catch (ClassNotFoundException cnfe) + { + return bundleResourceLoader.loadClass(className); + } + } + + +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/OsgiConfigurationProvider.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,336 @@ +package org.apache.struts2.osgi; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +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.jar.JarEntry; +import java.util.jar.JarInputStream; + +import javax.servlet.ServletContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.felix.framework.Felix; +import org.apache.felix.framework.cache.BundleCache; +import org.apache.felix.framework.util.FelixConstants; +import org.apache.felix.framework.util.StringMap; +import org.apache.struts2.views.velocity.VelocityManager; +import org.apache.velocity.app.Velocity; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkEvent; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.ConfigurationProvider; +import com.opensymphony.xwork2.config.entities.PackageConfig; +import com.opensymphony.xwork2.inject.ContainerBuilder; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ResolverUtil.Test; +import com.opensymphony.xwork2.util.location.LocatableProperties; + +public class OsgiConfigurationProvider implements ConfigurationProvider { + + private static final Log log = LogFactory.getLog(OsgiConfigurationProvider.class); + + private Felix felix; + private Map<String,Bundle> bundles = Collections.synchronizedMap(new HashMap<String,Bundle>()); + private Configuration configuration; + private BundleContext bundleContext; + private ServletContext servletContext; + private boolean bundlesChanged = false; + + private ObjectFactory objectFactory; + + @Inject + public void setBundleAccessor(BundleAccessor acc) { + acc.setBundles(bundles); + } + + @Inject + public void setServletContext(ServletContext ctx) { + this.servletContext = ctx; + } + + @Inject + public void setObjectFactory(ObjectFactory factory) { + this.objectFactory = factory; + } + + @Inject + public void setVelocityManager(VelocityManager vm) { + Properties props = new Properties(); + props.setProperty("osgi.resource.loader.description","OSGI bundle loader"); + props.setProperty("osgi.resource.loader.class", BundleResourceLoader.class.getName()); + props.setProperty(Velocity.RESOURCE_LOADER, "strutsclass,osgi"); + vm.setVelocityProperties(props); + } + + public void destroy() { + try { + felix.stop(); + } catch (BundleException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + bundles = null; + } + + public void init(Configuration configuration) throws ConfigurationException { + loadOsgi(); + 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); + } + Set bundleNames = new HashSet(); + if (refs != null) { + for (ServiceReference ref : refs) { + if (!bundleNames.contains(ref.getBundle().getSymbolicName())) { + bundleNames.add(ref.getBundle().getSymbolicName()); + log.info("Loading packages from bundle "+ref.getBundle().getSymbolicName()); + PackageLoader loader = (PackageLoader) bundleContext.getService(ref); + for (PackageConfig pkg : loader.loadPackages(ref.getBundle(), objectFactory, configuration.getPackageConfigs())) { + configuration.addPackageConfig(pkg.getName(), pkg); + } + } + } + } + bundlesChanged = false; + } + + public synchronized boolean needsReload() { + return bundlesChanged; + } + + public void register(ContainerBuilder builder, LocatableProperties props) + throws ConfigurationException { + } + + protected void loadOsgi() { + Map configMap = new StringMap(false); + configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES, + "org.osgi.framework; version=1.4.0," + + "org.osgi.service.packageadmin; version=1.2.0," + + "org.osgi.service.startlevel; version=1.0.0," + + "org.osgi.service.url; version=1.0.0"); + + Set<String> bundlePaths = new HashSet<String>(findInPackage("bundles")); + log.info("Loading Struts bundles "+bundlePaths); + + StringBuilder sb = new StringBuilder(); + for (String path : bundlePaths) { + sb.append(path).append(" "); + } + + configMap.put(FelixConstants.AUTO_START_PROP + ".1", + sb.toString()); + configMap.put(BundleCache.CACHE_PROFILE_DIR_PROP, "/tmp/foo");//System.getProperty("tmp.dir")); + configMap.put(BundleCache.CACHE_DIR_PROP, "jim"); + configMap.put(FelixConstants.EMBEDDED_EXECUTION_PROP, "true"); + configMap.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false"); + configMap.put("org.osgi.framework.bootdelegation", "org.apache.*"); + configMap.put("osgi.parentClassloader", "app"); + configMap.put("felix.log.level", "4"); + configMap.put(FelixConstants.BUNDLE_CLASSPATH, "."); + + try { + List list = new ArrayList(); + list.add(new BundleRegistration()); + // Now create an instance of the framework. + felix = new Felix(configMap, list); + felix.start(); + } + catch (Exception ex) { + throw new ConfigurationException("Couldn't start Felix (OSGi)", ex); + } + + // Wait for all bundles to load + while (bundles.size() < bundlePaths.size()) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + } + + class BundleRegistration implements BundleActivator, BundleListener { + + public void start(BundleContext context) throws Exception { + context.addBundleListener(this); + bundleContext = context; + } + + public void stop(BundleContext arg0) throws Exception { + // TODO Auto-generated method stub + + } + + public void bundleChanged(BundleEvent evt) { + if (evt.getType() == evt.INSTALLED) { + log.debug("Installed bundle "+evt.getBundle().getSymbolicName()); + bundles.put(evt.getBundle().getLocation(), evt.getBundle()); + bundlesChanged = true; + } + + // Copy out all view files + /*if (evt.getType() == evt.STARTED) { + Enumeration e = evt.getBundle().findEntries("/view/", null, true); + while (e != null && e.hasMoreElements()) { + URL url = (URL) e.nextElement(); + System.out.println("found view url: "+url); + } + } + */ + } + + } + + /** + * Scans for classes starting at the package provided and descending into subpackages. + * Each class is offered up to the Test as it is discovered, and if the Test returns + * true the class is retained. Accumulated classes can be fetched by calling + * [EMAIL PROTECTED] #getClasses()}. + * + * @param test an instance of [EMAIL PROTECTED] Test} that will be used to filter classes + * @param packageName the name of the package from which to start scanning for + * classes, e.g. [EMAIL PROTECTED] net.sourceforge.stripes} + */ + public List<String> findInPackage(String packageName) { + packageName = packageName.replace('.', '/'); + Enumeration<URL> urls; + List<String> paths = new ArrayList<String>(); + + try { + urls = Thread.currentThread().getContextClassLoader().getResources(packageName); + } + catch (IOException ioe) { + log.warn("Could not read package: " + packageName, ioe); + return paths; + } + + while (urls.hasMoreElements()) { + try { + String urlPath = urls.nextElement().getFile(); + urlPath = URLDecoder.decode(urlPath, "UTF-8"); + + // If it's a file in a directory, trim the stupid file: spec + if ( urlPath.startsWith("file:") ) { + urlPath = urlPath.substring(5); + } + + // Else it's in a JAR, grab the path to the jar + if (urlPath.indexOf('!') > 0) { + urlPath = urlPath.substring(0, urlPath.indexOf('!')); + } + + //log.info("Scanning for classes in [" + urlPath + "] matching criteria: " + test); + File file = new File(urlPath); + if ( file.isDirectory() ) { + loadImplementationsInDirectory(paths, packageName, file); + } + else { + loadImplementationsInJar(paths, packageName, file); + } + } + catch (IOException ioe) { + log.warn("could not read entries", ioe); + } + } + return paths; + } + + + /** + * Finds matches in a physical directory on a filesystem. Examines all + * files within a directory - if the File object is not a directory, and ends with <i>.class</i> + * the file is loaded and tested to see if it is acceptable according to the Test. Operates + * recursively to find classes within a folder structure matching the package structure. + * + * @param test a Test used to filter the classes that are discovered + * @param parent the package name up to this directory in the package hierarchy. E.g. if + * /classes is in the classpath and we wish to examine files in /classes/org/apache then + * the values of <i>parent</i> would be <i>org/apache</i> + * @param location a File object representing a directory + */ + private void loadImplementationsInDirectory(List<String> paths, String parent, File location) { + File[] files = location.listFiles(); + StringBuilder builder = null; + + for (File file : files) { + builder = new StringBuilder(100); + builder.append(parent).append("/").append(file.getName()); + String packageOrClass = ( parent == null ? file.getName() : builder.toString() ); + + if (file.isDirectory()) { + loadImplementationsInDirectory(paths, packageOrClass, file); + } + else if (file.getName().endsWith(".jar")) { + try { + paths.add(file.toURL().toString()); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + /** + * Finds matching classes within a jar files that contains a folder structure + * matching the package structure. If the File is not a JarFile or does not exist a warning + * will be logged, but no error will be raised. + * + * @param test a Test used to filter the classes that are discovered + * @param parent the parent package under which classes must be in order to be considered + * @param jarfile the jar file to be examined for classes + */ + private void loadImplementationsInJar(List<String> paths, String parent, File jarfile) { + + try { + JarEntry entry; + JarInputStream jarStream = new JarInputStream(new FileInputStream(jarfile)); + + while ( (entry = jarStream.getNextJarEntry() ) != null) { + String name = entry.getName(); + if (!entry.isDirectory() && name.startsWith(parent) && name.endsWith(".jar")) { + paths.add(jarfile.toURL()+"!"+entry.getName()); + } + } + } + catch (IOException ioe) { + log.error("Could not search jar file '" + jarfile + "' due to an IOException", ioe); + } + } + +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/PackageLoader.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,14 @@ +package org.apache.struts2.osgi; + +import java.util.List; +import java.util.Map; + +import org.osgi.framework.Bundle; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.entities.PackageConfig; + +public interface PackageLoader { + List<PackageConfig> loadPackages(Bundle bundle, ObjectFactory objectFactory, Map<String,PackageConfig> map) throws ConfigurationException; +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/StrutsActivator.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/StrutsActivator.java?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/StrutsActivator.java (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/java/org/apache/struts2/osgi/StrutsActivator.java Sun Jul 29 06:45:02 2007 @@ -0,0 +1,19 @@ +package org.apache.struts2.osgi; + +import java.util.Properties; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class StrutsActivator implements BundleActivator { + + public void start(final BundleContext ctx) throws Exception { + ctx.registerService(PackageLoader.class.getName(), new BundlePackageLoader(), new Properties()); + ctx.getBundle().loadClass("org.apache.struts2.osgi.BundleAccessor"); + ctx.getBundle().loadClass("org.twdata.osgitest.foo.FooAction"); + } + + public void stop(BundleContext ctx) throws Exception { + } + +} Added: struts/sandbox/trunk/struts2-osgi-plugin/src/main/resources/struts-plugin.xml URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-osgi-plugin/src/main/resources/struts-plugin.xml?view=auto&rev=560720 ============================================================================== --- struts/sandbox/trunk/struts2-osgi-plugin/src/main/resources/struts-plugin.xml (added) +++ struts/sandbox/trunk/struts2-osgi-plugin/src/main/resources/struts-plugin.xml Sun Jul 29 06:45:02 2007 @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!DOCTYPE struts PUBLIC + "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" + "http://struts.apache.org/dtds/struts-2.0.dtd"> + +<struts> + <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" /> + + <constant name="struts.objectFactory" value="osgi" /> + <constant name="struts.objectFactory.delegate" value="struts" /> + +</struts>