avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From blorit...@apache.org
Subject cvs commit: avalon-excalibur/fortress/src/tools/org/apache/avalon/fortress/tools ComponentMetaInfoCollector.java LoaderGenerator.java ServiceCollector.java
Date Tue, 18 Mar 2003 17:11:10 GMT
bloritsch    2003/03/18 09:11:09

  Modified:    fortress build.xml default.properties
  Added:       fortress/src/java/org/apache/avalon/fortress/impl/role
                        ServiceRoleManager.java
               fortress/src/java/org/apache/avalon/fortress/util
                        Service.java
               fortress/src/tools/org/apache/avalon/fortress/tools
                        ComponentMetaInfoCollector.java
                        LoaderGenerator.java ServiceCollector.java
  Log:
  add support for build time collection of roles and implementations--changes will come when we standardize on names
  
  Revision  Changes    Path
  1.78      +43 -13    avalon-excalibur/fortress/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/fortress/build.xml,v
  retrieving revision 1.77
  retrieving revision 1.78
  diff -u -r1.77 -r1.78
  --- build.xml	12 Mar 2003 13:23:50 -0000	1.77
  +++ build.xml	18 Mar 2003 17:11:09 -0000	1.78
  @@ -16,7 +16,8 @@
           <pathelement location="${avalon-logkit.jar}"/> <!-- deprecated -->
           <pathelement location="${logkit.jar}"/>
           <pathelement location="${commons-collections.jar}"/>
  -        <pathelement location="${util.concurrent.jar}"/>
  +	<pathelement location="${util.concurrent.jar}"/>
  +	<pathelement location="${qdox.jar}"/>
           <pathelement location="${excalibur-instrument.jar}"/>
           <pathelement location="${excalibur-instrument-manager.jar}"/>
           <pathelement location="${excalibur-instrument-manager-interfaces.jar}"/>
  @@ -170,18 +171,6 @@
               <exclude name="**/*Assembly*.java" unless="include.meta"/>
           </javac>
   
  -        <javac srcdir="src/ng"
  -            destdir="${build.classes}"
  -            debug="${build.debug}"
  -            optimize="${build.optimize}"
  -            deprecation="${build.deprecation}"
  -            target="1.2">
  -            <classpath refid="build.path"/>
  -            <include name="**/*.java"/>
  -            <exclude name="**/util/*.java" unless="include.meta"/>
  -            <exclude name="**/container/**/*.java" unless="include.meta"/>
  -        </javac>
  -
           <!-- copy resources to same location as .class files -->
           <copy todir="${build.classes}">
               <fileset dir="${java.dir}">
  @@ -192,6 +181,23 @@
   
       </target>
   
  +    <target name="compile-tools" depends="compile">
  +
  +	<mkdir dir="${build.dir}/tools"/>
  +
  +	<javac srcdir="src/tools"
  +	       destdir="${build.dir}/tools"
  +               debug="${build.debug}"
  +               optimize="${build.optimize}"
  +               deprecation="${build.deprecation}"
  +	       target="1.2">
  +          <classpath>
  +	    <path refid="build.path"/>
  +	    <pathelement location="${build.classes}"/>
  +	  </classpath>
  +	</javac>
  +   </target>
  +
       <!-- Compiles the unit test source code -->
       <target name="compile-test" depends="compile,dependencies-test,path-builder" description="Compiles the source code">
           <mkdir dir="${build.testsrc}"/>
  @@ -237,6 +243,30 @@
               </filterset>
           </copy>
   
  +    </target>
  +
  +    <target name="tools-jar" depends="compile-tools, jar" description="Generates the ANT task tool jar">
  +        <mkdir dir="${build.lib}"/>
  +
  +        <jar jarfile="${build.lib}/${tools.jar.name}"
  +	    basedir="${build.dir}/tools"
  +            compress="${build.compress}">
  +            <manifest>
  +              <attribute name="Extension-Name" value="${name}-tools"/>
  +              <attribute name="Specification-Vendor" value="Apache Software Foundation"/>
  +              <attribute name="Specification-Version" value="1.0"/>
  +              <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
  +              <attribute name="Implementation-Version" value="${package-version}"/>
  +            </manifest>
  +            <exclude name="**/test/**"/>
  +            <zipfileset dir="${build.conf}" prefix="META-INF/">
  +                <include name="LICENSE.txt"/>
  +	    </zipfileset>
  +	    <fileset dir="${build.classes}">
  +	        <include name="**/util/Service*"/>
  +		<include name="**/role/Service*"/>
  +	    </fileset>
  +        </jar>
       </target>
   
       <!-- Creates all the .jar file -->
  
  
  
  1.68      +6 -0      avalon-excalibur/fortress/default.properties
  
  Index: default.properties
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/fortress/default.properties,v
  retrieving revision 1.67
  retrieving revision 1.68
  diff -u -r1.67 -r1.68
  --- default.properties	11 Mar 2003 15:15:23 -0000	1.67
  +++ default.properties	18 Mar 2003 17:11:09 -0000	1.68
  @@ -19,6 +19,9 @@
   # ----- Doug Lea's Concurrent Utils, version 1.3 or later -----
   util.concurrent.jar=${basedir}/../event/lib/util.concurrent-1.3.1.jar
   
  +# ----- QDox Jar ----
  +qdox.jar=${basedir}/../lib/qdox-1.1.jar
  +
   # ----- Excalibur Lifecycle -----
   excalibur-lifecycle.home=${basedir}/../lifecycle
   excalibur-lifecycle.lib=${excalibur-lifecycle.home}/build/lib
  @@ -165,6 +168,9 @@
   
   #  name of jar file
   jar.name = ${name}-${version}.jar
  +
  +#  name of tools jar file
  +tools.jar.name = ${name}-tools-${version}.jar
   
   #  property indicating directory where all distribution archives are placed
   dist.base = distributions
  
  
  
  1.1                  avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/impl/role/ServiceRoleManager.java
  
  Index: ServiceRoleManager.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "D-Haven" and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.avalon.fortress.impl.role;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.net.URL;
  import java.util.Collections;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Properties;
  import java.util.Set;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import org.apache.avalon.fortress.RoleManager;
  import org.apache.avalon.fortress.impl.handler.PerThreadComponentHandler;
  import org.apache.avalon.fortress.impl.handler.PoolableComponentHandler;
  import org.apache.avalon.fortress.impl.handler.ThreadSafeComponentHandler;
  import org.apache.avalon.fortress.util.Service;
  import org.apache.avalon.framework.activity.Initializable;
  
  /**
   * ServiceRoleManager follows some simple rules to dynamically gather all
   * services and the meta-information into one role manager.  This really gets
   * rid of the need of multiple role managers.  It uses a set of entries in your
   * JARs to do its magic.
   * 
   * <p><code><b>/services.list</b></code></p>
   * 
   * <p>
   *   This lists all the services that are <em>defined</em> in this jar.
   * </p>
   * 
   * <p><code><b>/META-INF/services/</b><i>my.class.Name</i></code></p>
   * 
   * <p>
   *   One entry for each service where there are implementations for a role.  This
   *   follows the JAR services mechanism.
   * </p>
   * 
   * <p><code><i>/my/class/Implementation.meta</i></code></p>
   * 
   * <p>
   *   There is one entry sitting right beside every implementation class.  This
   *   holds all the meta information for the associated class.  It is a simple
   *   properties file.
   * </p>
   * 
   * <h3>ANT Tasks available</h3>
   * <p>
   *   We have a couple of ANT tasks to make this really easy.  If you add this
   *   to your ANT build script (customizing it to make it work in your environment),
   *   it will make your life alot easier:
   * </p>
   * 
   * <pre>
   *   &lt;taskdef name="collect-metainfo" classname="org.d_haven.guiapp.tools.ComponentMetaInfoCollector"&gt;
   *     &lt;classpath&gt;
   *       &lt;path refid="project.class.path"/&gt;
   *       &lt;pathelement path="${tools.dir}/guiapp-tools.jar"/&gt;
   *     &lt;/classpath&gt;
   *   &lt;/taskdef&gt;
   * 
   *   &lt;taskdef name="collect-services" classname="org.d_haven.guiapp.tools.ServiceCollector"&gt;
   *     &lt;classpath&gt;
   *       &lt;path refid="project.class.path"/&gt;
   *       &lt;pathelement path="${tools.dir}/guiapp-tools.jar"/&gt;
   *     &lt;/classpath&gt;
   *   &lt;/taskdef&gt;
   *      
   *   &lt;collect-metainfo destdir="${build.classes}"&gt;
   *      &lt;fileset dir="${src.dir}"/&gt;
   *   &lt;/collect-metainfo&gt;
   *
   *   &lt;collect-services inputjar="${build.dir}/${name}-core.jar"
   *                     outputjar="${lib.dir}/${name}.jar"/&gt;
   * </pre>
   * 
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   */
  public class ServiceRoleManager extends AbstractRoleManager implements Initializable
  {
      /** Translate from scope to component handler */
      private static final Map m_scopeMap;
      /** Used to split words in class names */
      private static final Pattern upperCase = Pattern.compile("([A-Z]+)");
      
      // Initialize the scope map
      static
      {
          Map scopes = new HashMap();
          scopes.put("container", ThreadSafeComponentHandler.class.getName());
          scopes.put("thread", PerThreadComponentHandler.class.getName());
          scopes.put("request", PoolableComponentHandler.class.getName());
          
          m_scopeMap = Collections.unmodifiableMap(scopes);
      }
  
      /**
       * Create a ServiceRoleManager.
       */
      public ServiceRoleManager()
      {
          super(null);
      }
      
      /**
       * Create a ServiceRoleManager with a parent RoleManager.
       * 
       * @param parent
       */
      public ServiceRoleManager(RoleManager parent)
      {
          super(parent, null);
      }
      
      /**
       * Create a ServiceRoleManager with the supplied classloader and
       * parent RoleManager.
       * 
       * @param parent
       * @param loader
       */
      public ServiceRoleManager(RoleManager parent, ClassLoader loader)
      {
          super(parent, loader);
      }
  
      /**
       * Convert a Component implmentation classname into a shorthand
       * name.  It assumes all classnames for a particular component is
       * unique.
       * 
       * @param string  The classname of a component
       * @return String the short name
       */
      public static final String createShortName(String className)
      {
          Matcher matcher = upperCase.matcher(className.substring(className.lastIndexOf('.') + 1));
          StringBuffer shortName = new StringBuffer();
   
          while (matcher.find())
          {
              if ( shortName.length() == 0 )
              {
                  matcher.appendReplacement(shortName, "$1");;
              }
              else
              {
                  matcher.appendReplacement(shortName, "-$1");
              }
          }
          
          matcher.appendTail(shortName);
          
          return shortName.toString().toLowerCase();
      }
  
      /**
       * Initialize the ServiceRoleManager by looking at all the services and
       * classes available in the system.
       */
      public void initialize() throws Exception
      {
          Set services = new HashSet();
          
          Enumeration enum = getLoader().getResources("services.list");
          while (enum.hasMoreElements())
          {
              readEntries(services, (URL)enum.nextElement());
          }
          
          Iterator it = services.iterator();
          while (it.hasNext())
          {
              String role = (String)it.next();
              getLogger().debug("Adding service: " + role);
              setupImplementations(role);
          }
      }
  
      /**
       * Get all the implementations of a service and set up their meta
       * information.
       * 
       * @param role
       */
      private void setupImplementations(String role)
          throws IOException, ClassNotFoundException
      {
          Iterator it = Service.providers(getLoader().loadClass(role));
          
          while (it.hasNext())
          {
              String impl = ((Class)it.next()).getName();
              getLogger().debug("Reading meta info for " + impl);
              readMeta(role, impl);
          }
      }
  
      /**
       * Read the meta information in and actually add the role.
       * 
       * @param role
       * @param implementation
       */
      private void readMeta(String role, String implementation)
      {
          Properties meta = new Properties();
          
          try
          {
              meta.load(getLoader().getResourceAsStream(translate(implementation)));
          }
          catch (IOException ioe)
          {
              getLogger().error("Could not load meta information for " +
                                implementation + ", skipping this class.");
              return;
          }
          
          String shortName = meta.getProperty("avalon.configname", createShortName(implementation));
          String handler = getHandler(meta);
          
          addRole(shortName, role, implementation, handler);
      }
  
      /**
       * Get the name of the requested component handler.
       * 
       * @param meta
       * @return String
       */
      private String getHandler(Properties meta)
      {
          String scope = meta.getProperty("avalon.scope", null);
          String handler = null;
          
          if (null != scope)
          {
              handler = (String)m_scopeMap.get(scope);
          }
          else
          {
              handler = meta.getProperty("fortress.handler");
          }
          
          if (null == handler)
          {
              handler = PerThreadComponentHandler.class.getName();
          }
          
          return handler;
      }
  
      /**
       * Translate a class name into the meta file name.
       * 
       * @param implementation
       * @return String
       */
      private String translate(String implementation)
      {
          String entry = implementation.replace('.', '/');
          entry += ".meta"; 
          return entry;
      }
  
      /**
       * Read entries in a list file and add them all to the provided Set.
       * 
       * @param services
       * @param url
       */
      private void readEntries(Set entries, URL url)
          throws IOException
      {
          BufferedReader reader = new BufferedReader( new InputStreamReader(url.openStream()) );
          
          String entry = reader.readLine();
          while (entry != null)
          {
              entries.add(entry);
              entry = reader.readLine();
          }
          
          reader.close();
      }
  }
  
  
  
  1.1                  avalon-excalibur/fortress/src/java/org/apache/avalon/fortress/util/Service.java
  
  Index: Service.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "D-Haven" and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.avalon.fortress.util;
  
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.net.URL;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Set;
  
  import javax.swing.ImageIcon;
  
  /**
   * This class handles looking up service providers on the class path.
   * It implements the system described in:
   *
   * <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service Provider">
   * File Specification Under Service Provider</a>.  Note that this interface is
   * very similar to the one they describe whiehc seems to be missing in the JDK.
   *
   * This class adapted from <code>org.apache.batik.util.Service</code>
   *
   * @author <a href="bloritsch@apache.org">Berin Loritsch</a>
   * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
   * @version 1.0
   */
  public final class Service
  {
      private static String SERVICES = "META-INF/services/";
      private static HashMap providers = new HashMap();
  
      /**
       * Private constructor to keep from instantiating this class
       */
      private Service()
      {}
  
      /**
       * Get all the providers for the specified services.
       *
       * @param klass  the interface <code>Class</code>
       *
       * @return an <code>Iterator</code> for the providers.
       */
      public static synchronized Iterator providers( Class klass )
      {
          String serviceFile = SERVICES + klass.getName();
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
  
          if( null == loader )
          {
              loader = klass.getClassLoader();
          }
  
          Set providerSet = ( Set )providers.get( serviceFile );
  
          if( null == providerSet )
          {
              providerSet = new HashSet();
              Enumeration enum = null;
              boolean errorOccurred = false;
  
              providers.put( serviceFile, providerSet );
  
              try
              {
                  enum = loader.getResources( serviceFile );
              }
              catch( IOException ioe )
              {
                  errorOccurred = true;
              }
  
              if( !errorOccurred )
              {
                  while( enum.hasMoreElements() )
                  {
                      try
                      {
                          URL url = ( URL )enum.nextElement();
                          InputStream is = url.openStream();
                          BufferedReader reader = new BufferedReader(
                              new InputStreamReader( is,
                              "UTF-8" ) );
  
                          String line = reader.readLine();
                          while( null != line )
                          {
                              try
                              {
                                  int comment = line.indexOf( '#' );
  
                                  if( comment > -1 )
                                  {
                                      line = line.substring( 0, comment );
                                  }
  
                                  line.trim();
  
                                  if( line.length() > 0 )
                                  {
                                      // We just want the types, not the instances
                                      providerSet.add( loader.loadClass( line ) );
                                  }
                              }
                              catch( Exception e )
                              {
                                  // try the next line
                              }
  
                              line = reader.readLine();
                          }
                      }
                      catch( Exception e )
                      {
                          // try the next file
                      }
                  }
              }
          }
  
          return providerSet.iterator();
      }
  
      /**
       * Load an icon from the JARs
       * 
       * @param entry      Path to the icon
       * @return ImageIcon The ImageIcon from the loaded icon.
       */
      public static ImageIcon loadLibraryIcon( String entry )
      {
          ClassLoader loader = Thread.currentThread().getContextClassLoader();
          return new ImageIcon( loader.getResource( entry ) );
      }
  }
  
  
  
  1.1                  avalon-excalibur/fortress/src/tools/org/apache/avalon/fortress/tools/ComponentMetaInfoCollector.java
  
  Index: ComponentMetaInfoCollector.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "D-Haven" and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.avalon.fortress.tools;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Properties;
  import java.util.Set;
  
  import org.apache.avalon.fortress.impl.handler.FactoryComponentHandler;
  import org.apache.avalon.fortress.impl.handler.PerThreadComponentHandler;
  import org.apache.avalon.fortress.impl.handler.PoolableComponentHandler;
  import org.apache.avalon.fortress.impl.handler.ThreadSafeComponentHandler;
  import org.apache.avalon.fortress.impl.role.ServiceRoleManager;
  import org.apache.avalon.framework.thread.SingleThreaded;
  import org.apache.avalon.framework.thread.ThreadSafe;
  import org.apache.tools.ant.BuildException;
  
  import com.thoughtworks.qdox.ant.AbstractQdoxTask;
  import com.thoughtworks.qdox.model.DocletTag;
  import com.thoughtworks.qdox.model.JavaClass;
  import com.thoughtworks.qdox.model.Type;
  
  /**
   * @author bloritsch
   *
   * To change this generated comment go to 
   * Window>Preferences>Java>Code Generation>Code and Comments
   */
  public class ComponentMetaInfoCollector extends AbstractQdoxTask
  {
      /**
       * The services to write the meta info for.
       */
      private Set m_services = new HashSet();
      
      /**
       * The destination directory for metadata files.
       */
      private File m_destDir;
      
      /**
       * The service list destination.
       */
      private File m_serviceFile;
      
      public void setDestDir( final File destDir )
      {
          m_destDir = destDir;
      }
  
      /**
       * Execute generator task.
       */
      public void execute()
          throws BuildException
      {
          validate();
  
          final String message =
              "Writing Info descriptors as property files (.meta).";
          log( message );
  
          super.execute();
  
          try
          {
              writeInfoMetaData();
              
              PrintWriter writer = new PrintWriter( new FileWriter( m_serviceFile ) );
              
              Iterator it = m_services.iterator();
              while (it.hasNext())
              {
                  writer.println(it.next());
              }
              
              writer.close();
          }
          catch( final Exception e )
          {
              throw new BuildException( e.toString(), e );
          }
      }
  
      /**
       * Validate that the parameters are valid.
       */
      private void validate()
      {
          if( null == m_destDir )
          {
              final String message =
                  "DestDir (" + m_destDir + ") not specified";
              throw new BuildException( message );
          }
          
          if( !m_destDir.isDirectory() )
          {
              final String message =
                  "DestDir (" + m_destDir + ") is not a directory.";
              throw new BuildException( message );
          }
  
          if( !m_destDir.exists() && !m_destDir.mkdirs() )
          {
              final String message =
                  "DestDir (" + m_destDir + ") could not be created.";
              throw new BuildException( message );
          }
          
          m_serviceFile = new File(m_destDir, "services.list");
      }
  
      /**
       * Output the metadata files.
       *
       * @throws IOException If a problem writing output
       */
      private void writeInfoMetaData() throws IOException
      {
          final Iterator it = allClasses.iterator();
          while( it.hasNext() )
          {
              final JavaClass javaClass = (JavaClass)it.next();
              DocletTag tag = javaClass.getTagByName( "avalon.service" );
              if( null != tag )
              {
                  m_services.add(javaClass.getFullyQualifiedName());
              }
              else
              {
                  tag = javaClass.getTagByName( "avalon.component" );
                  if( null != tag )
                  {
                      Properties meta = new Properties();
                      
                      prepareMetaInfo(meta, javaClass);
                      
                      File metaFile = getOutputFileForClass(javaClass.getFullyQualifiedName());
                      FileOutputStream fos = new FileOutputStream(metaFile);
                      meta.store(fos, "Meta-Information for " + javaClass.getFullyQualifiedName());
                  }
              }
          }
      }
  
      /**
       * @param meta
       * @param javaClass
       */
      private void prepareMetaInfo(Properties meta, JavaClass javaClass)
      {
          DocletTag avalonScope = javaClass.getTagByName("avalon.scope");
          DocletTag fortressHandler = javaClass.getTagByName("fortress.handler");
          String scope = null;
          String handler = null;
          
          if ( avalonScope == null && fortressHandler == null )
          {
              Type[] interfaces = javaClass.getImplements();
              for (int i = 0; i < interfaces.length && handler != null; i++)
              {
                  if(interfaces[i].getClass().equals(ThreadSafe.class))
                  {
                      handler = ThreadSafeComponentHandler.class.getName();
                  }
                  else if (interfaces[i].getClass().getName().equals("org.apache.avalon.excalibur.pool.Poolable") ||
                           interfaces[i].getClass().getName().equals("org.apache.avalon.excalibur.pool.Recyclable"))
                  {
                      handler = PoolableComponentHandler.class.getName();
                  }
                  else if (interfaces[i].getClass().equals(SingleThreaded.class))
                  {
                      handler = FactoryComponentHandler.class.getName();
                  }
              }
          }
          
          if (null != avalonScope)
          {
              scope = avalonScope.getValue();
          }
          else if (handler != null)
          {
              handler = (null == fortressHandler) ? PerThreadComponentHandler.class.getName() : fortressHandler.getValue();
          }
          
          if ( null != scope ) meta.setProperty("avalon.scope", scope);
          if ( null != handler ) meta.setProperty("fortress.handler", handler);
          
          DocletTag avalonConfigName = javaClass.getTagByName("avalon.configname");
          if ( null == avalonConfigName ) avalonConfigName = javaClass.getTagByName("fortress.configname");
  
          meta.setProperty("avalon.configname", (avalonConfigName == null) ? ServiceRoleManager.createShortName(javaClass.getName()) : avalonConfigName.getValue() );
      }
  
      /**
       * Determine the file for specified {@link ComponentInfo}.
       *
       * @param classname the fully qualified name of file to generate
       * @return the file for info
       * @throws IOException if unable to determine base file
       */
      private File getOutputFileForClass( final String classname )
          throws IOException
      {
          String filename =
              classname.replace( '.', File.separatorChar );
          
          filename += ".meta";
          return new File( m_destDir, filename ).getCanonicalFile();
      }
  }
  
  
  
  1.1                  avalon-excalibur/fortress/src/tools/org/apache/avalon/fortress/tools/LoaderGenerator.java
  
  Index: LoaderGenerator.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "D-Haven" and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.avalon.fortress.tools;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Properties;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.taskdefs.Jar;
  import org.apache.tools.ant.taskdefs.Manifest;
  import org.apache.tools.ant.types.ZipFileSet;
  
  /**
   * Creates a Loader archive.
   *
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   */
  public class LoaderGenerator
      extends Jar
  {
      private File m_splashScreen;
      private File m_buildNumber;
      private String m_name;
      private String m_version;
      private String m_lookAndFeel;
      private String m_proxy;
  
      public LoaderGenerator()
      {
          archiveType = "jar";
          emptyBehavior = "fail";
      }
  
      public void setDest( final File file )
      {
          setDestFile( file );
      }
  
      public void setSplashScreen( final File screen )
      {
          m_splashScreen = screen;
  
          if( !m_splashScreen.exists() )
          {
              final String message =
                  "Splash Screen: " + m_splashScreen + " does not exist.";
              throw new BuildException( message, getLocation() );
          }
  
          if( !m_splashScreen.isFile() )
          {
              final String message =
                  "Splash Screen: " + m_splashScreen + " is not a file.";
              throw new BuildException( message, getLocation() );
          }
      }
  
      public void setBuildNumberFile( final File buildNumber )
      {
          m_buildNumber = buildNumber;
  
          if( !m_buildNumber.exists() )
          {
              final String message =
                  "Build Number File: " + m_buildNumber + " does not exist.";
              throw new BuildException( message, getLocation() );
          }
  
          if( !m_buildNumber.isFile() )
          {
              final String message =
                  "Build Number File: " + m_buildNumber + " is not a file.";
              throw new BuildException( message, getLocation() );
          }
      }
  
      public void setAppName( final String appName )
      {
          m_name = appName;
  
          if( null == m_name || m_name.length() == 0 )
          {
              final String message =
                  "Application Name must be set.";
              throw new BuildException( message, getLocation() );
          }
      }
  
      public void setVersion( final String version )
      {
          m_version = version;
  
          if( null == m_version || m_version.length() == 0 )
          {
              final String message = "Application Version must be supplied.";
              throw new BuildException( message, getLocation() );
          }
      }
      
      public void setLookAndFeel( final String laf )
      {
          m_lookAndFeel = laf;
  
          if( null == m_lookAndFeel || m_lookAndFeel.length() == 0 )
          {
              final String message = "Look and Feel must be supplied.";
              throw new BuildException( message, getLocation() );
          }
      }
      
      public void setProxy( final String proxyClassName )
      {
          m_proxy = proxyClassName;
          
          if( null == m_proxy || m_proxy.length() == 0 )
          {
              final String message = "Application Proxy class name must be supplied.";
              throw new BuildException( message, getLocation() );
          }
          
          log("Warning, you are overriding the default application proxy class.");
      }
  
      public void execute()
          throws BuildException
      {
          if( null == m_splashScreen )
          {
              final String message = "splashscreen attribute is required";
              throw new BuildException( message, getLocation() );
          }
          if( null == m_name )
          {
              final String message = "name attribute is required";
              throw new BuildException( message, getLocation() );
          }
          if( null == m_version )
          {
              final String message = "version attribute is required";
              throw new BuildException( message, getLocation() );
          }
          if( null == m_proxy )
          {
              m_proxy = "org.d_haven.guiapp.container.FortressRunner";
          }
          if ( null == m_lookAndFeel )
          {
              m_lookAndFeel = "system";
          }
          
          File propFile = null;
          try
          {
              Properties props = new Properties();
              
              String build = "0";
              if (null != m_buildNumber)
              {
                  FileInputStream bfis = new FileInputStream(m_buildNumber);
                  Properties buildProps = new Properties();
                  buildProps.load(bfis);
                  bfis.close();
                  build = buildProps.getProperty("build.number");
              }
              
              props.put("app.name", m_name);
              props.put("app.version", m_version);
              props.put("app.build", build);
              props.put("app.laf", m_lookAndFeel);
              props.put("app.proxy", m_proxy);
              
              propFile = File.createTempFile("app", ".properties");
              propFile.deleteOnExit();
              FileOutputStream pos = new FileOutputStream(propFile);
              props.store(pos, "#Application constants");
              pos.close();
  
              Manifest manifest = Manifest.getDefaultManifest();
              Manifest.Attribute attr = new Manifest.Attribute();
              attr.setName("Main-Class");
              attr.setValue("org.d_haven.guiapp.Main");
              manifest.addConfiguredAttribute(attr);
              
              addConfiguredManifest(manifest);
              
              mergeArchive();
          }
          catch (Exception e)
          {
              e.printStackTrace();
              throw new BuildException("Could not create properties", getLocation());
          }
  
          pushFile( "META-INF/app.properties", propFile );
          pushFile( "org/d_haven/guiapp/splashscreen.jpg", m_splashScreen);
  
          super.execute();
      }
      
      private void mergeArchive()
          throws IOException
      {
          File loaderJar = File.createTempFile("loader", ".jar");
          loaderJar.deleteOnExit();
          InputStream resourceJar = getClass().getClassLoader().getResourceAsStream("loader.jar");
          FileOutputStream fos = new FileOutputStream(loaderJar);
          int length = -1;
          byte[] buffer = new byte[1024];
          
          while ( (length = resourceJar.read(buffer)) > 0 )
          {
              fos.write(buffer,0,length);
          }
          
          resourceJar.close();
          fos.close();
          
          final ZipFileSet zipFileSet = new ZipFileSet();
          zipFileSet.setSrc(loaderJar);
          zipFileSet.setIncludes("org/**");
          
          addFileset(zipFileSet);
      }
  
      private void pushFile( final String path, final File file )
      {
          final ZipFileSet zipFileSet = new ZipFileSet();
          zipFileSet.setDir( new File( file.getParent() ) );
          zipFileSet.setIncludes( file.getName() );
          zipFileSet.setFullpath( path );
          super.addFileset( zipFileSet );
      }
  
      protected void cleanUp()
      {
          super.cleanUp();
  
          m_splashScreen = null;
          m_name = null;
          m_version = null;
          m_lookAndFeel = null;
          m_proxy = null;
      }
  }
  
  
  
  1.1                  avalon-excalibur/fortress/src/tools/org/apache/avalon/fortress/tools/ServiceCollector.java
  
  Index: ServiceCollector.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation. All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software
   *    itself, if and wherever such third-party acknowledgments
   *    normally appear.
   *
   * 4. The names "D-Haven" and "Apache Software Foundation"
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.avalon.fortress.tools;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.FileReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.lang.reflect.Modifier;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.jar.JarEntry;
  import java.util.jar.JarFile;
  import java.util.jar.JarOutputStream;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  
  /**
   * Look at all the classes in a JAR file and determine if they
   * implement a specified service.  When we are done, serialize the
   * list to the appropriate services file.
   * 
   * @author <a href="bloritsch.at.apache.org">Berin Loritsch</a>
   */
  public class ServiceCollector extends Task
  {
      private File m_serviceList;
      private Map m_serviceMap;
      private final Set m_services = new HashSet();
      private File m_inJar = null;
      private File m_outJar = null;
      
      /**
       * Add elements of the form:
       * 
       * <service name="org.apache.package.MyInterface/>
       * 
       * @param service  The ServiceElement to add
       */
      public void addConfiguredService(ServiceElement service)
      {
          String serviceName = service.getName();
          
          if (null == serviceName || "".equals(serviceName.trim()))
          {
              String message = "Must supply a Service Name";
              throw new BuildException(message, getLocation());
          }
          
          m_services.add(serviceName);
      }
      
      /**
       * Support the attribute "inputjar".
       * 
       * @param input  The File representing a JAR file.
       */
      public void setInputJar(File input)
      {
          if ( null == input || input.isDirectory() )
          {
              String message = "Jar attribute is not a file";
              throw new BuildException(message, getLocation());
          }
          
          m_inJar = input;
      }
      
      /**
       * Support the attribute "outputjar".
       * 
       * @param input  The File representing a JAR file.
       */
      public void setOutputJar(File output)
      {
          if ( null == output || output.isDirectory() )
          {
              String message = "Jar attribute is not a file";
              throw new BuildException(message, getLocation());
          }
          
          m_outJar = output;
      }
      
      public void setServiceList(File serviceList)
      {
          if ( null == serviceList || serviceList.isDirectory() )
          {
              String message = "ServiceList attribute is not a file";
              throw new BuildException(message, getLocation());
          }
          
          m_serviceList = serviceList;
      }
      
      /**
       * Perform the actual checks to extract services.
       */
      public void execute()
      {
          if ( m_inJar == null )
          {
              throw new BuildException("Input Jar Attribute must be set", getLocation());
          }
          
          if ( m_outJar == null )
          {
              throw new BuildException("Output Jar Attribute must be set", getLocation());
          }
          
          if ( m_inJar.getAbsolutePath().equals(m_outJar.getAbsolutePath()))
          {
              throw new BuildException("The two jars cannot be the same.", getLocation());
          }
          
          log("Collecting Services", Project.MSG_INFO);
          
          try
          {
              URLClassLoader loader = new URLClassLoader(new URL[]{m_inJar.toURL()}, getClass().getClassLoader());
              FileOutputStream out = new FileOutputStream(m_outJar);
              
              try
              {
                  Enumeration enum = loader.getResources("services.list");
                  while (enum.hasMoreElements())
                  {
                      URL resource = (URL)enum.nextElement();
                      BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream()));
                      readServiceList(reader);
                      reader.close();
                  }
              }
              catch (IOException ioe)
              {
                  throw new BuildException(ioe);
              }
          
              if ( m_serviceList != null )
              {
                  BufferedReader reader;
                  try
                  {
                      reader = new BufferedReader(new FileReader(m_serviceList));
                      readServiceList(reader);
                      reader.close();
                  }
                  catch (FileNotFoundException fnfe)
                  {
                      throw new BuildException(fnfe);
                  }
                  catch (IOException ioe)
                  {
                      throw new BuildException(ioe);
                  }
              }
          
              if ( m_services.isEmpty() )
              {
                  log("No services selected.", Project.MSG_WARN);
              }
  
              JarFile jarFile = new JarFile(m_inJar);
              JarOutputStream outJar = new JarOutputStream(out, jarFile.getManifest());
              
              m_serviceMap = new HashMap();
              Iterator it = m_services.iterator();
              while(it.hasNext())
              {
                  String name = it.next().toString();
  
                  try
                  {
                      Class klass = loader.loadClass(name);
                      
                      if ( klass.isInterface() )
                      {
                          m_serviceMap.put(klass, new LinkedList());
                      }
                  }
                  catch(Exception e)
                  {
                      log(name + " is not an interface", Project.MSG_WARN);
                  }
              }
              
              Enumeration entries = jarFile.entries();
              while (entries.hasMoreElements())
              {
                  JarEntry entry = (JarEntry)entries.nextElement();
                  String name = entry.getName();
                  
                  if (name.endsWith(".class"))
                  {
                      try
                      {
                          String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
                          Class klass = loader.loadClass(className);
                          
                          checkClass(klass);
                      }
                      catch (Exception e)
                      {
                          log(e.getMessage(), Project.MSG_VERBOSE);
                      }
                  }
                  
                  if ( ! "META-INF/MANIFEST.MF".equals(name) )
                  {
                      if ("services.list".equals(name))
                      {
                          entry = new JarEntry("services.list");
                          outJar.putNextEntry(entry);
                          
                          Iterator services = m_services.iterator();
                          while (services.hasNext())
                          {
                              String service = (String)services.next();
                              service += "\n";
                              outJar.write(service.getBytes());
                          }
                      }
                      else
                      {
                          outJar.putNextEntry(entry);
                          
                          InputStream entryStream = jarFile.getInputStream(entry);
                          int length = -1;
                          byte[] buffer = new byte[1024];
                      
                          // Read the entry and write it to the temp jar.
                      
                          while ((length = entryStream.read(buffer)) != -1)
                          {
                               outJar.write(buffer, 0, length);
                          }
                      }
                  }
              }
              
              it = m_serviceMap.keySet().iterator();
              while (it.hasNext())
              {
                  Class iface = (Class)it.next();
                  String name = iface.getName();
                  JarEntry entry = new JarEntry("META-INF/services/" + name);
                  outJar.putNextEntry(entry);
                  
                  List impls = (List)m_serviceMap.get(iface);
                  Iterator imit = impls.iterator();
                  while(imit.hasNext())
                  {
                      String implementation = ((Class)imit.next()).getName();
                      implementation += "\n";
                      outJar.write(implementation.getBytes());
                  }
              }
  
              outJar.close();
              jarFile.close();
              m_inJar.deleteOnExit();
              
              log("Deleting the input jar", Project.MSG_INFO);
          }
          catch (Exception e)
          {
              e.printStackTrace();
              throw new BuildException("Could not process JAR: " + m_inJar.getName());
          }
      }
  
      public void readServiceList(BufferedReader reader) throws IOException
      {
          String line = reader.readLine();
          while ( line != null )
          {
              m_services.add(line);
              line = reader.readLine();
          }
      }
  
      /**
       * The core of the checkClass() logic.  It validates the
       * class passed in against the set of interfaces we have.
       * 
       * @param klass
       */
      protected void checkClass(Class klass)
      {
          if ( ! klass.isInterface() )
          {
              if ( ! Modifier.isAbstract(klass.getModifiers()) )
              {
                  Iterator it = m_serviceMap.keySet().iterator();
                  while (it.hasNext())
                  {
                     Class iface = (Class) it.next();
                     
                     if ( iface.isAssignableFrom(klass) )
                     {
                         log(klass.getName() + " implements " + iface.getName(), Project.MSG_VERBOSE);
                         
                         List list = (List) m_serviceMap.get(iface);
                         list.add(klass);
                     }
                  }
              }
          }
      }
      
      /**
       * Clean up after ourselves so we can reuse this.
       */
      protected void cleanUp()
      {
          m_services.clear();
          m_serviceMap.clear();
          m_inJar = null;
          m_outJar = null;
      }
      
      /**
       * The ServiceElement that is used to handle the
       * <service name="foo"/> nested elements.
       */
      public static class ServiceElement
      {
          private String _name = "";
          
          /**
           * Get the name of the service.
           * 
           * @return String
           */
          public String getName()
          {
              return _name;
          }
          
          /**
           * Sets the name of the service.
           * @param name
           */
          public void setName(String name)
          {
              _name = name;
          }
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org


Mime
View raw message