[jboss-cvs] jboss-seam/src/main/org/jboss/seam/deployment ...
Peter Muir
peter at bleepbleep.org.uk
Mon Jan 14 06:29:49 EST 2008
User: pmuir
Date: 08/01/14 06:29:48
Modified: src/main/org/jboss/seam/deployment
package-info.java Scanner.java
Added: src/main/org/jboss/seam/deployment
AbstractScanner.java DeploymentHandler.java
GroovyHotDeploymentStrategy.java
AbstractDeploymentHandler.java
NamespaceDeploymentHandler.java
ComponentDeploymentHandler.java
DeploymentStrategy.java URLScanner.java
SimpleDeploymentStrategy.java
GroovyDeploymentHandler.java
HotDeploymentStrategy.java
Removed: src/main/org/jboss/seam/deployment
ComponentScanner.java GroovyComponentScanner.java
NamespaceScanner.java
Log:
JBSEAM-2488, JBSEAM2489, rework deployment to be pluggable and extensible
Revision Changes Path
1.2 +2 -3 jboss-seam/src/main/org/jboss/seam/deployment/package-info.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: package-info.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/deployment/package-info.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- package-info.java 22 Jun 2007 09:18:41 -0000 1.1
+++ package-info.java 14 Jan 2008 11:29:48 -0000 1.2
@@ -1,7 +1,6 @@
/**
- * Scanners for automatically loading components
- * from deployed archives. Internal implementation
- * stuff.
+ * Scanners and handlers for automatically loading components
+ * from deployed archives.
*/
package org.jboss.seam.deployment;
1.32 +6 -306 jboss-seam/src/main/org/jboss/seam/deployment/Scanner.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Scanner.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/src/main/org/jboss/seam/deployment/Scanner.java,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- Scanner.java 2 Jan 2008 21:56:02 -0000 1.31
+++ Scanner.java 14 Jan 2008 11:29:48 -0000 1.32
@@ -1,316 +1,16 @@
-//$Id: Scanner.java,v 1.31 2008/01/02 21:56:02 alesj Exp $
package org.jboss.seam.deployment;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.URLDecoder;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.jar.JarInputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javassist.bytecode.AnnotationsAttribute;
-import javassist.bytecode.ClassFile;
-import javassist.bytecode.annotation.MemberValue;
-import org.jboss.seam.log.LogProvider;
-import org.jboss.seam.log.Logging;
-
/**
- * Abstract class for scanning archives in the
- * Seam classpath.
- *
- * @author Thomas Heute
- * @author Gavin King
- * @author Norman Richards
+ * @author Pete Muir
*
*/
-public abstract class Scanner
+public interface Scanner
{
- private static final LogProvider log = Logging.getLogProvider(Scanner.class);
-
- protected String resourceName;
- protected ClassLoader classLoader;
- protected static Boolean useVFS;
-
- public Scanner(String resourceName)
- {
- this( resourceName, Thread.currentThread().getContextClassLoader() );
- }
-
- public Scanner(String resourceName, ClassLoader classLoader)
- {
- this.resourceName = resourceName;
- this.classLoader = classLoader;
- ClassFile.class.getPackage(); //to force loading of javassist, throwing an exception if it is missing
- }
-
- protected static boolean useVFS()
- {
- if (useVFS == null)
- {
- try
- {
- Class.forName("org.jboss.virtual.VFS");
- // OK, we have VFS
- // but are we in JBoss5 and also not using Embedded
- useVFS = isJBoss5() && !isEmbedded();
- if (useVFS)
- log.info("Using JBoss VFS for scanning.");
- }
- catch(Throwable t)
- {
- useVFS = false;
- log.debug("Using default file utils for scanning.");
- }
- }
- return useVFS;
- }
-
- protected static boolean isJBoss5()
- {
- try
- {
- Class versionClass = Class.forName("org.jboss.Version");
- Method getVersionInstance = versionClass.getMethod("getInstance");
- Object versionInstance = getVersionInstance.invoke(null);
- Method getMajor = versionClass.getMethod("getMajor");
- Object major = getMajor.invoke(versionInstance);
- return major != null && major.equals(5);
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- protected static boolean isEmbedded()
- {
- try
- {
- Class.forName("org.jboss.embedded.Bootstrap");
- if (log.isTraceEnabled())
- log.trace("Using JBoss Embedded.");
- return true;
- }
- catch(Exception e)
- {
- return false;
- }
- }
-
- public static String filenameToClassname(String filename)
- {
- return filename.substring( 0, filename.lastIndexOf(".class") )
- .replace('/', '.').replace('\\', '.');
- }
-
- public static String filenameToPackage(String filename)
- {
- return filename.substring( 0, filename.lastIndexOf(".class") )
- .replace('/', '.').replace('\\', '.');
- }
-
- protected void scan()
- {
- Set<String> paths = new HashSet<String>();
- if (resourceName==null)
- {
- for ( URL url: getURLsFromClassLoader() )
- {
- String urlPath = url.getFile();
- if ( urlPath.endsWith("/") )
- {
- urlPath = urlPath.substring( 0, urlPath.length()-1 );
- }
- paths.add( urlPath );
- }
- }
- else
- {
- try
- {
- Enumeration<URL> urlEnum = classLoader.getResources(resourceName);
- while ( urlEnum.hasMoreElements() )
- {
- String urlPath = urlEnum.nextElement().getFile();
- urlPath = URLDecoder.decode(urlPath, "UTF-8");
- if ( urlPath.startsWith("file:") )
- {
- if (useVFS())
- urlPath = "vfs" + urlPath;
- else
- urlPath = urlPath.substring(5);
- }
- if ( urlPath.indexOf('!')>0 )
- {
- urlPath = urlPath.substring(0, urlPath.indexOf('!'));
- }
- else
- {
- File dirOrArchive = new File(urlPath);
- if ( resourceName!=null && resourceName.lastIndexOf('/')>0 )
- {
- //for META-INF/components.xml
- dirOrArchive = dirOrArchive.getParentFile();
- }
- urlPath = dirOrArchive.getParent();
- }
- paths.add(urlPath);
- }
- }
- catch (IOException ioe)
- {
- log.warn("could not read: " + resourceName, ioe);
- return;
- }
- }
-
- for ( String urlPath: paths )
- {
- try
- {
- log.info("scanning: " + urlPath);
- File file = new File(urlPath);
- if ( file.isDirectory() )
- {
- handleDirectory(file, null);
- }
- else if (useVFS())
- {
- URL url = new URL(urlPath);
- handleArchiveByURL(url);
- }
- else
- {
- handleArchiveByFile(file);
- }
- }
- catch (IOException ioe)
- {
- log.warn("could not read entries", ioe);
- }
- }
- }
-
- protected URL[] getURLsFromClassLoader()
- {
- return ( (URLClassLoader) classLoader ).getURLs();
- }
-
-
- private void handleArchiveByFile(File file) throws IOException
- {
- log.debug("archive: " + file);
- ZipFile zip = new ZipFile(file);
- Enumeration<? extends ZipEntry> entries = zip.entries();
- while ( entries.hasMoreElements() )
- {
- ZipEntry entry = entries.nextElement();
- String name = entry.getName();
- log.debug("found: " + name);
- handleItem(name);
- }
- }
-
- private void handleArchiveByURL(URL url) throws IOException
- {
- log.debug("archive: " + url);
- JarInputStream inputStream = new JarInputStream(url.openStream());
- try
- {
- ZipEntry entry = inputStream.getNextEntry();
- while ( entry != null )
- {
- String name = entry.getName();
- log.debug("found: " + name);
- handleItem(name);
- entry = inputStream.getNextEntry();
- }
- }
- finally
- {
- inputStream.close();
- }
- }
-
- private void handleDirectory(File file, String path)
- {
- log.debug("directory: " + file);
- for ( File child: file.listFiles() )
- {
- String newPath = path==null ? child.getName() : path + '/' + child.getName();
- if ( child.isDirectory() )
- {
- handleDirectory(child, newPath);
- }
- else
- {
- handleItem(newPath);
- }
- }
- }
-
- abstract void handleItem(String name);
-
- protected ClassFile getClassFile(String name) throws IOException
- {
- InputStream stream = classLoader.getResourceAsStream(name);
- DataInputStream dstream = new DataInputStream(stream);
-
- try
- {
- return new ClassFile(dstream);
- }
- finally
- {
- dstream.close();
- stream.close();
- }
- }
- protected boolean hasAnnotation(ClassFile cf, Class<? extends Annotation> annotationType)
- {
- AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
- if ( visible != null )
- {
- return visible.getAnnotation( annotationType.getName() ) != null;
- }
- return false;
- }
+ public void scanClassLoader();
- protected String getAnnotationValue(ClassFile cf, Class<? extends Annotation> annotationType, String memberName)
- {
- AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
- if ( visible != null )
- {
- javassist.bytecode.annotation.Annotation annotation = visible.getAnnotation( annotationType.getName() );
- if (annotation==null)
- {
- return null;
- }
- else
- {
- MemberValue memberValue = annotation.getMemberValue(memberName);
- return memberValue==null ? null : memberValue.toString(); //TODO: toString() here is probably Bad ;-)
- }
- }
- else
- {
- return null;
- }
- }
+ public void scanResources();
- public static String componentFilename(String name)
- {
- return name.substring( 0, name.lastIndexOf(".class") ) + ".component.xml";
- }
+ public DeploymentStrategy getDeploymentStrategy();
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/AbstractScanner.java
Index: AbstractScanner.java
===================================================================
package org.jboss.seam.deployment;
import javassist.bytecode.ClassFile;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* @author Pete Muir
*
*/
public abstract class AbstractScanner implements Scanner
{
private static final LogProvider log = Logging.getLogProvider(Scanner.class);
private DeploymentStrategy deploymentStrategy;
public AbstractScanner(DeploymentStrategy deploymentStrategy)
{
this.deploymentStrategy = deploymentStrategy;
ClassFile.class.getPackage(); //to force loading of javassist, throwing an exception if it is missing
}
protected final void handleItem(String name)
{
log.trace("found " + name);
getDeploymentStrategy().handle(name);
}
public DeploymentStrategy getDeploymentStrategy()
{
return deploymentStrategy;
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/DeploymentHandler.java
Index: DeploymentHandler.java
===================================================================
package org.jboss.seam.deployment;
/**
* @author Pete Muir
*
*/
public interface DeploymentHandler
{
public void handle(String name, ClassLoader classLoader);
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/GroovyHotDeploymentStrategy.java
Index: GroovyHotDeploymentStrategy.java
===================================================================
package org.jboss.seam.deployment;
import groovy.lang.GroovyClassLoader;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.codehaus.groovy.control.CompilerConfiguration;
/**
* @author Pete Muir
*
*/
public class GroovyHotDeploymentStrategy extends HotDeploymentStrategy
{
private static final String DEFAULT_SCRIPT_EXTENSION = new CompilerConfiguration().getDefaultScriptExtension();
private ClassLoader classLoader;
private GroovyDeploymentHandler groovyDeploymentHandler;
public GroovyHotDeploymentStrategy(ClassLoader classLoader, File hotDeployDirectory)
{
super(classLoader, hotDeployDirectory);
if (super.getClassLoader() != null)
{
this.classLoader = new GroovyClassLoader(super.getClassLoader());
}
groovyDeploymentHandler = new GroovyDeploymentHandler(DEFAULT_SCRIPT_EXTENSION);
getDeploymentHandlers().put(GroovyDeploymentHandler.NAME, groovyDeploymentHandler);
}
@Override
public ClassLoader getClassLoader()
{
return classLoader;
}
@Override
public boolean isFromHotDeployClassLoader(Class componentClass)
{
//loaded by groovy or java
if (getClassLoader() == null)
{
return false;
}
else
{
ClassLoader classClassLoader = componentClass.getClassLoader().getParent(); //Groovy use an Inner Delegate CL
return classClassLoader == getClassLoader() || classClassLoader == getClassLoader().getParent();
}
}
@Override
public ClassLoader getScannableClassLoader()
{
if (classLoader != null)
{
return classLoader.getParent();
}
else
{
return null;
}
}
@Override
public Set<Class<Object>> getScannedComponentClasses()
{
Set<Class<Object>> set = new HashSet<Class<Object>>();
set.addAll(super.getScannedComponentClasses());
set.addAll(groovyDeploymentHandler.getClasses());
return Collections.unmodifiableSet(set);
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/AbstractDeploymentHandler.java
Index: AbstractDeploymentHandler.java
===================================================================
package org.jboss.seam.deployment;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.annotation.MemberValue;
/**
* @author Pete Muir
*
*/
public abstract class AbstractDeploymentHandler implements DeploymentHandler
{
public static String filenameToClassname(String filename)
{
return filename.substring( 0, filename.lastIndexOf(".class") )
.replace('/', '.').replace('\\', '.');
}
protected ClassFile getClassFile(String name, ClassLoader classLoader) throws IOException
{
InputStream stream = classLoader.getResourceAsStream(name);
DataInputStream dstream = new DataInputStream(stream);
try
{
return new ClassFile(dstream);
}
finally
{
dstream.close();
stream.close();
}
}
protected boolean hasAnnotation(ClassFile cf, Class<? extends Annotation> annotationType)
{
AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
if ( visible != null )
{
return visible.getAnnotation( annotationType.getName() ) != null;
}
return false;
}
protected String getAnnotationValue(ClassFile cf, Class<? extends Annotation> annotationType, String memberName)
{
AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
if ( visible != null )
{
javassist.bytecode.annotation.Annotation annotation = visible.getAnnotation( annotationType.getName() );
if (annotation==null)
{
return null;
}
else
{
MemberValue memberValue = annotation.getMemberValue(memberName);
return memberValue==null ? null : memberValue.toString(); //TODO: toString() here is probably Bad ;-)
}
}
else
{
return null;
}
}
public static String filenameToPackage(String filename)
{
return filename.substring( 0, filename.lastIndexOf(".class") )
.replace('/', '.').replace('\\', '.');
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/NamespaceDeploymentHandler.java
Index: NamespaceDeploymentHandler.java
===================================================================
package org.jboss.seam.deployment;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jboss.seam.annotations.Namespace;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* @author Pete Muir
*
*/
public class NamespaceDeploymentHandler extends AbstractDeploymentHandler
{
public static final String NAME = "org.jboss.seam.deployment.NamespaceDeploymentHandler";
private static final LogProvider log = Logging.getLogProvider(NamespaceDeploymentHandler.class);
private Set<Package> packages;
public NamespaceDeploymentHandler()
{
packages = new HashSet<Package>();
}
/**
* Returns packages with @Namespace declarations
*/
public Set<Package> getPackages()
{
return Collections.unmodifiableSet(packages);
}
public void handle(String name, ClassLoader classLoader)
{
if ( name.endsWith("/package-info.class") )
{
String packageName = filenameToPackageName(name);
Package pkg = getPackage(packageName, classLoader);
if (pkg == null)
{
log.warn("Cannot load package Dinfo for " + packageName);
}
else
{
if (pkg.getAnnotation(Namespace.class) != null)
{
packages.add(pkg);
}
}
}
}
private static String filenameToPackageName(String filename)
{
return filename.substring(0, filename.lastIndexOf("/package-info.class"))
.replace('/', '.').replace('\\', '.');
}
private static Package getPackage(String name, ClassLoader classLoader)
{
try
{
Class c = classLoader.loadClass(name + ".package-info");
return c != null ? c.getPackage() : null;
}
catch (Exception e)
{
return null;
}
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/ComponentDeploymentHandler.java
Index: ComponentDeploymentHandler.java
===================================================================
package org.jboss.seam.deployment;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javassist.bytecode.ClassFile;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* @author Pete Muir
*
*/
public class ComponentDeploymentHandler extends AbstractDeploymentHandler
{
public static final String NAME = "org.jboss.seam.deployment.ComponentDeploymentHandler";
private static final LogProvider log = Logging.getLogProvider(ComponentDeploymentHandler.class);
protected Set<Class<Object>> classes;
private Set<String> resources;
public ComponentDeploymentHandler()
{
classes = new HashSet<Class<Object>>();
resources = new HashSet<String>();
}
/**
* Returns only Seam components (ie: classes annotated with @Name)
*/
public Set<Class<Object>> getClasses()
{
return Collections.unmodifiableSet(classes);
}
public Set<String> getResources()
{
return Collections.unmodifiableSet(resources);
}
public void handle(String name, ClassLoader classLoader)
{
if (name.endsWith(".class"))
{
String classname = filenameToClassname(name);
String filename = componentFilename(name);
try
{
ClassFile classFile = getClassFile(name, classLoader);
boolean installable = ( hasAnnotation(classFile, Name.class) || classLoader.getResources(filename).hasMoreElements() )
&& !"false".equals( getAnnotationValue(classFile, Install.class, "value") );
if (installable)
{
log.trace("found component class: " + name);
classes.add( (Class<Object>) classLoader.loadClass(classname) );
}
}
catch (ClassNotFoundException cnfe)
{
log.debug("could not load class: " + classname, cnfe);
}
catch (NoClassDefFoundError ncdfe)
{
log.debug("could not load class (missing dependency): " + classname, ncdfe);
}
catch (IOException ioe)
{
log.debug("could not load classfile: " + classname, ioe);
}
}
else if (name.endsWith(".component.xml") || name.endsWith("/components.xml"))
{
// we want to skip over known meta-directories since Seam will auto-load these without a scan
if (!name.startsWith("WEB-INF/") && !name.startsWith("META-INF/"))
{
resources.add(name);
}
}
}
private static String componentFilename(String name)
{
return name.substring( 0, name.lastIndexOf(".class") ) + ".component.xml";
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/DeploymentStrategy.java
Index: DeploymentStrategy.java
===================================================================
package org.jboss.seam.deployment;
import static org.jboss.seam.util.Strings.split;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* @author Pete Muir
*
*/
public abstract class DeploymentStrategy
{
private static final LogProvider log = Logging.getLogProvider(DeploymentStrategy.class);
private Scanner scanner;
private Map<String, DeploymentHandler> deploymentHandlers;
public DeploymentStrategy()
{
this.deploymentHandlers = new HashMap<String, DeploymentHandler>();
}
public abstract void scan();
public abstract String[] getResourceNames();
protected Scanner getScanner()
{
if (scanner == null)
{
scanner = createScanner();
}
return scanner;
}
public abstract ClassLoader getClassLoader();
public abstract ClassLoader getScannableClassLoader();
public Map<String, DeploymentHandler> getDeploymentHandlers()
{
return this.deploymentHandlers;
}
public void handle(String name)
{
for (String key: getDeploymentHandlers().keySet())
{
DeploymentHandler deploymentHandler = getDeploymentHandlers().get(key);
deploymentHandler.handle(name, getClassLoader());
}
}
private Scanner createScanner()
{
Scanner scanner = getScannerFromResource();
if (scanner == null)
{
scanner = getScannerFromSystemProperty();
}
if (scanner == null)
{
log.debug("Using default URLScanner");
scanner = new URLScanner(this);
}
return scanner;
}
private Scanner getScannerFromSystemProperty()
{
String scanners = System.getProperty("org.jboss.seam.deployment.scanners");
if (scanners != null)
{
log.debug("Tring to load scanner from system property");
Scanner scanner = loadScanner(scanners);
if (scanner != null)
{
log.debug("Using " + scanner.getClass().getName() + " specified in /META-INF/seam-scanner.properties");
return scanner;
}
}
return null;
}
private Scanner getScannerFromResource()
{
// Load scanner.properties from the classpath, try to
// load any scanners specified there
try
{
String scanners = ResourceBundle.getBundle("META-INF/seam-scanner", Locale.getDefault(), getClassLoader()).getString("org.jboss.seam.deployment.scanners");
log.debug("Tring to load scanner from /META-INF/seam-scanner.properties");
Scanner scanner = loadScanner(scanners);
if (scanner != null)
{
log.debug("Using " + scanner.getClass().getName() + " specified in /META-INF/seam-scanner.properties");
return scanner;
}
log.debug("Unable to load any scanner from /META-INF/seam-scanner.properties");
}
catch (MissingResourceException e)
{
// no-op
}
return null;
}
private Scanner loadScanner(String scanners)
{
for (String className : split(scanners, ":"))
{
Scanner scanner = instantiateScanner(className);
if (scanner != null)
{
return scanner;
}
}
return null;
}
private Scanner instantiateScanner(String className)
{
try
{
Class<Scanner> scannerClass = (Class<Scanner>) getClassLoader().loadClass(className);
Constructor<Scanner> constructor = scannerClass.getConstructor(new Class[] {DeploymentStrategy.class});
return constructor.newInstance( new Object[] {this} );
}
catch (ClassNotFoundException e)
{
log.trace("Unable to use " + className + " as scanner (class not found)", e);
}
catch (NoClassDefFoundError e)
{
log.trace("Unable to use " + className + " as scanner (dependency not found)", e);
}
catch (ClassCastException e)
{
log.trace("Unable to use " + className + " as scanner (class does not implement org.jboss.seam.deployment.Scanner)");
}
catch (InstantiationException e)
{
log.trace("Unable to instantiate scanner " + className, e);
}
catch (IllegalAccessException e)
{
log.trace("Unable to instantiate scanner " + className, e);
}
catch (SecurityException e)
{
log.trace(className + " must declare public " + className + "( ClassLoader classLoader, String ... resourceNames )", e);
}
catch (NoSuchMethodException e)
{
log.trace(className + " must declare public " + className + "( ClassLoader classLoader, String ... resourceNames )", e);
}
catch (IllegalArgumentException e)
{
log.trace(className + " must declare public " + className + "( ClassLoader classLoader, String ... resourceNames )", e);
}
catch (InvocationTargetException e)
{
log.trace(className + " must declare public " + className + "( ClassLoader classLoader, String ... resourceNames )", e);
}
return null;
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/URLScanner.java
Index: URLScanner.java
===================================================================
package org.jboss.seam.deployment;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* Abstract class for scanning archives in the
* Seam classpath.
*
* @author Thomas Heute
* @author Gavin King
* @author Norman Richards
* @author Pete Muir
*
*/
public class URLScanner extends AbstractScanner
{
private static final LogProvider log = Logging.getLogProvider(URLScanner.class);
public URLScanner(DeploymentStrategy deploymentStrategy)
{
super(deploymentStrategy);
}
public void scanClassLoader()
{
Set<String> paths = new HashSet<String>();
for ( URL url: getURLsFromClassLoader() )
{
String urlPath = url.getFile();
if ( urlPath.endsWith("/") )
{
urlPath = urlPath.substring( 0, urlPath.length()-1 );
}
paths.add( urlPath );
}
handle(paths);
}
public void scanResources()
{
Set<String> paths = new HashSet<String>();
for (String resourceName : getDeploymentStrategy().getResourceNames())
{
try
{
Enumeration<URL> urlEnum = getDeploymentStrategy().getClassLoader().getResources(resourceName);
while ( urlEnum.hasMoreElements() )
{
String urlPath = urlEnum.nextElement().getFile();
urlPath = URLDecoder.decode(urlPath, "UTF-8");
if ( urlPath.startsWith("file:") )
{
urlPath = urlPath.substring(5);
}
if ( urlPath.indexOf('!')>0 )
{
urlPath = urlPath.substring(0, urlPath.indexOf('!'));
}
else
{
File dirOrArchive = new File(urlPath);
if ( resourceName!=null && resourceName.lastIndexOf('/')>0 )
{
//for META-INF/components.xml
dirOrArchive = dirOrArchive.getParentFile();
}
urlPath = dirOrArchive.getParent();
}
paths.add(urlPath);
}
}
catch (IOException ioe)
{
log.warn("could not read: " + resourceName, ioe);
}
}
handle(paths);
}
private void handle(Set<String> paths)
{
for ( String urlPath: paths )
{
try
{
log.debug("scanning: " + urlPath);
File file = new File(urlPath);
if ( file.isDirectory() )
{
handleDirectory(file, null);
}
else
{
handleArchiveByFile(file);
}
}
catch (IOException ioe)
{
log.warn("could not read entries", ioe);
}
}
}
private URL[] getURLsFromClassLoader()
{
if (getDeploymentStrategy().getScannableClassLoader() instanceof URLClassLoader)
{
return ( (URLClassLoader) getDeploymentStrategy().getScannableClassLoader()).getURLs();
}
else
{
return new URL[0];
}
}
private void handleArchiveByFile(File file) throws IOException
{
log.debug("archive: " + file);
ZipFile zip = new ZipFile(file);
Enumeration<? extends ZipEntry> entries = zip.entries();
while ( entries.hasMoreElements() )
{
ZipEntry entry = entries.nextElement();
String name = entry.getName();
handleItem(name);
}
}
private void handleDirectory(File file, String path)
{
log.debug("directory: " + file);
for ( File child: file.listFiles() )
{
String newPath = path==null ? child.getName() : path + '/' + child.getName();
if ( child.isDirectory() )
{
handleDirectory(child, newPath);
}
else
{
handleItem(newPath);
}
}
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/SimpleDeploymentStrategy.java
Index: SimpleDeploymentStrategy.java
===================================================================
package org.jboss.seam.deployment;
import java.util.Set;
/**
* @author Pete Muir
*
*/
public class SimpleDeploymentStrategy extends DeploymentStrategy
{
private ClassLoader classLoader;
public static final String[] RESOURCE_NAMES = {"seam.properties", "META-INF/seam.properties", "META-INF/components.xml"};
private ComponentDeploymentHandler componentDeploymentHandler;
private NamespaceDeploymentHandler namespaceDeploymentHandler;
public SimpleDeploymentStrategy(ClassLoader classLoader)
{
this.classLoader = Thread.currentThread().getContextClassLoader();
componentDeploymentHandler = new ComponentDeploymentHandler();
getDeploymentHandlers().put(ComponentDeploymentHandler.NAME, componentDeploymentHandler);
namespaceDeploymentHandler = new NamespaceDeploymentHandler();
getDeploymentHandlers().put(NamespaceDeploymentHandler.NAME, namespaceDeploymentHandler);
}
@Override
public ClassLoader getClassLoader()
{
return classLoader;
}
@Override
public ClassLoader getScannableClassLoader()
{
return getClassLoader();
}
@Override
public String[] getResourceNames()
{
return RESOURCE_NAMES;
}
public Set<Class<Object>> getScannedComponentClasses()
{
return componentDeploymentHandler.getClasses();
}
public Set<String> getScannedComponentResources()
{
return componentDeploymentHandler.getResources();
}
public Set<Package> getScannedNamespaces()
{
return namespaceDeploymentHandler.getPackages();
}
@Override
public void scan()
{
getScanner().scanResources();
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/GroovyDeploymentHandler.java
Index: GroovyDeploymentHandler.java
===================================================================
package org.jboss.seam.deployment;
import groovy.lang.GroovyRuntimeException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.codehaus.groovy.control.CompilationFailedException;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* @author Pete Muir
*
*/
public class GroovyDeploymentHandler extends AbstractDeploymentHandler
{
private static final LogProvider log = Logging.getLogProvider(GroovyDeploymentHandler.class);
public static final String NAME = "org.jboss.seam.deployment.GroovyDeploymentHandler";
private final String groovyFileExtension;
private Set<Class<Object>> classes;
public GroovyDeploymentHandler(String groovyFileExtension)
{
this.groovyFileExtension = groovyFileExtension;
this.classes = new HashSet<Class<Object>>();
}
public Set<Class<Object>> getClasses()
{
return Collections.unmodifiableSet(classes);
}
public void handle(String name, ClassLoader classLoader)
{
if (name.endsWith(groovyFileExtension))
{
log.debug("Found a groovy file: " + name);
String classname = filenameToGroovyname(name);
String filename = groovyComponentFilename(name);
BufferedReader buffReader = null;
try
{
InputStream stream = classLoader.getResourceAsStream(name);
//TODO is BufferedInputStream necessary?
buffReader = new BufferedReader(new InputStreamReader(stream));
String line = buffReader.readLine();
while (line != null)
{
if (line.indexOf("@Name") != -1 || line.indexOf("@" + Name.class.getName()) != -1)
{
//possibly a Seam component
log.debug("Groovy file possibly a Seam component: " + name);
Class<Object> groovyClass = (Class<Object>) classLoader.loadClass(classname);
Install install = groovyClass.getAnnotation(Install.class);
boolean installable = ( install == null || install.value() )
&& ( groovyClass.isAnnotationPresent(Name.class)
|| classLoader.getResources(filename).hasMoreElements() );
if (installable)
{
log.debug("found groovy component class: " + name);
classes.add(groovyClass);
}
break;
}
line = buffReader.readLine();
}
}
catch (ClassNotFoundException cnfe)
{
log.debug("could not load groovy class: " + classname, cnfe);
}
catch (NoClassDefFoundError ncdfe)
{
log.debug("could not load groovy class (missing dependency): " + classname, ncdfe);
}
catch (IOException ioe)
{
log.debug("could not load groovy file: " + classname, ioe);
}
catch( CompilationFailedException e) {
log.info("Compilation error in Groovy file:" + classname, e);
}
catch(GroovyRuntimeException e) {
log.info("Unknown error reading Groovy file:" + classname, e);
}
finally
{
if (buffReader != null) {
try
{
buffReader.close();
}
catch (IOException e)
{
log.trace("Could not close stream");
}
}
}
}
}
private String filenameToGroovyname(String filename)
{
return filename.substring(0, filename.lastIndexOf(groovyFileExtension))
.replace('/', '.').replace('\\', '.');
}
private String groovyComponentFilename(String name)
{
return name.substring(0, name.lastIndexOf(groovyFileExtension)) + ".component.xml";
}
}
1.1 date: 2008/01/14 11:29:48; author: pmuir; state: Exp;jboss-seam/src/main/org/jboss/seam/deployment/HotDeploymentStrategy.java
Index: HotDeploymentStrategy.java
===================================================================
package org.jboss.seam.deployment;
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Set;
import org.jboss.seam.util.Reflections;
/**
* @author Pete Muir
*
*/
public class HotDeploymentStrategy extends DeploymentStrategy
{
public static final String HOT_DEPLOYMENT_DIRECTORY_PATH = "WEB-INF/dev";
private ClassLoader hotDeployClassLoader;
private File[] hotDeploymentPaths;
private ComponentDeploymentHandler componentDeploymentHandler;
public HotDeploymentStrategy(ClassLoader classLoader, File hotDeployDirectory)
{
initHotDeployClassLoader(classLoader, hotDeployDirectory);
componentDeploymentHandler = new ComponentDeploymentHandler();
getDeploymentHandlers().put(ComponentDeploymentHandler.NAME, componentDeploymentHandler);
}
private void initHotDeployClassLoader(ClassLoader classLoader, File hotDeployDirectory)
{
try
{
if (hotDeployDirectory.exists())
{
URL url = hotDeployDirectory.toURL();
URL[] urls = { url };
hotDeployClassLoader = new URLClassLoader(urls, classLoader);
hotDeploymentPaths = new File[] { hotDeployDirectory };
}
}
catch (MalformedURLException mue)
{
throw new RuntimeException(mue);
}
}
public File[] getHotDeploymentPaths()
{
return hotDeploymentPaths;
}
public boolean isFromHotDeployClassLoader(Class componentClass)
{
return componentClass.getClassLoader() == hotDeployClassLoader;
}
public static HotDeploymentStrategy createInstance(String className, ClassLoader classLoader, File hotDeployDirectory)
{
try
{
Class initializer = Reflections.classForName(className);
Constructor ctr = initializer.getConstructor(ClassLoader.class, File.class);
return (HotDeploymentStrategy) ctr.newInstance(classLoader, hotDeployDirectory);
}
catch (Exception e)
{
throw new IllegalArgumentException("No such deployment strategy " + className, e);
}
}
@Override
public ClassLoader getClassLoader()
{
return hotDeployClassLoader;
}
@Override
public String[] getResourceNames()
{
return null;
}
@Override
public ClassLoader getScannableClassLoader()
{
return getClassLoader();
}
public Set<Class<Object>> getScannedComponentClasses()
{
return componentDeploymentHandler.getClasses();
}
@Override
public void scan()
{
getScanner().scanClassLoader();
}
}
More information about the jboss-cvs-commits
mailing list