[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