You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2003/10/13 03:28:27 UTC

cvs commit: avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit DefaultRunnableKernel.java UnitHelper.java AbstractMerlinTestCase.java UnitException.java UnitRuntimeException.java package.html

mcconnell    2003/10/12 18:28:27

  Modified:    merlin/composition/api/src/java/org/apache/avalon/composition/model
                        ContainmentModel.java
               merlin/kernel/bootstrap/src/etc merlin.properties
               merlin/kernel/impl project.xml
               merlin/kernel/impl/src/java/org/apache/avalon/merlin/kernel/impl
                        DefaultKernel.java DefaultLoader.java
               merlin/kernel/plugin project.xml
               merlin/kernel/spi project.xml
               merlin/kernel/spi/src/java/org/apache/avalon/merlin/kernel
                        Kernel.java
               merlin/kernel/unit maven.xml project.xml
               merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit
                        AbstractMerlinTestCase.java UnitException.java
                        UnitRuntimeException.java package.html
  Added:       merlin/kernel/unit/src/etc merlin.properties
               merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit
                        DefaultRunnableKernel.java UnitHelper.java
  Log:
  Updates supporting a dynamically loader kernel.
  
  Revision  Changes    Path
  1.3       +3 -3      avalon/merlin/composition/api/src/java/org/apache/avalon/composition/model/ContainmentModel.java
  
  Index: ContainmentModel.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/composition/api/src/java/org/apache/avalon/composition/model/ContainmentModel.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ContainmentModel.java	12 Oct 2003 17:12:45 -0000	1.2
  +++ ContainmentModel.java	13 Oct 2003 01:28:26 -0000	1.3
  @@ -141,8 +141,8 @@
       * Addition of a new subsidiary containment model within
       * the containment context using a supplied url.
       *
  -    * @param url a url referencing a containment profile
  -    * @param url containment configuration targets
  +    * @param block a url referencing a containment profile
  +    * @param config containment configuration targets
       * @return the model created using the derived profile and configuration
       * @exception ModelException if an error occurs during model establishment
       */
  
  
  
  1.2       +1 -1      avalon/merlin/kernel/bootstrap/src/etc/merlin.properties
  
  Index: merlin.properties
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/bootstrap/src/etc/merlin.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- merlin.properties	24 Sep 2003 09:32:51 -0000	1.1
  +++ merlin.properties	13 Oct 2003 01:28:26 -0000	1.2
  @@ -21,7 +21,7 @@
   merlin.spi.classpath.2=avalon-composition:avalon-composition-spi;1.0b1
   merlin.spi.classpath.3=avalon-activation:avalon-activation-spi;1.0b1
   merlin.spi.classpath.4=avalon-repository:avalon-repository-spi;1.0b1
  -merlin.spi.classpath.5=merlin:merlin-kernel-spi;3.0b1
  +merlin.spi.classpath.5=merlin:merlin-kernel-spi;3.1b2
   
   #
   # the bootstrap classpath
  
  
  
  1.3       +2 -2      avalon/merlin/kernel/impl/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/impl/project.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- project.xml	7 Oct 2003 17:44:09 -0000	1.2
  +++ project.xml	13 Oct 2003 01:28:26 -0000	1.3
  @@ -9,7 +9,7 @@
     <name>Merlin Kernel Implementation</name>
     <package>org.apache.avalon.merlin</package>
   
  -  <currentVersion>3.1b1</currentVersion>
  +  <currentVersion>3.1b2</currentVersion>
     <inceptionYear>2002</inceptionYear>
     <shortDescription>Merlin Kernel Implementation</shortDescription>
   
  @@ -37,7 +37,7 @@
       <dependency>
         <groupId>merlin</groupId>
         <artifactId>merlin-kernel-spi</artifactId>
  -      <version>3.1b1</version>
  +      <version>3.1b2</version>
       </dependency>
   
       <!-- avalon dependecies -->
  
  
  
  1.4       +11 -1     avalon/merlin/kernel/impl/src/java/org/apache/avalon/merlin/kernel/impl/DefaultKernel.java
  
  Index: DefaultKernel.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/impl/src/java/org/apache/avalon/merlin/kernel/impl/DefaultKernel.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DefaultKernel.java	12 Oct 2003 17:12:45 -0000	1.3
  +++ DefaultKernel.java	13 Oct 2003 01:28:26 -0000	1.4
  @@ -423,6 +423,16 @@
           return m_block;
       }
   
  +   /**
  +    * Return the Logger for the specified category.
  +    * @param category the category path
  +    * @return the logging channel
  +    */
  +    public Logger getLoggerForCategory( final String category )
  +    {
  +        return m_context.getLoggerForCategory( category );
  +    }
  +
       //--------------------------------------------------------------
       // DefaultKernel
       //--------------------------------------------------------------
  
  
  
  1.2       +2 -2      avalon/merlin/kernel/impl/src/java/org/apache/avalon/merlin/kernel/impl/DefaultLoader.java
  
  Index: DefaultLoader.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/impl/src/java/org/apache/avalon/merlin/kernel/impl/DefaultLoader.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultLoader.java	12 Oct 2003 17:16:30 -0000	1.1
  +++ DefaultLoader.java	13 Oct 2003 01:28:26 -0000	1.2
  @@ -59,9 +59,9 @@
       * line arguments, the repository established for runtime deployment
       * may be changed.
       *
  -    * @param system the bootstrap repository from which merlin 
  +    * @param repository the bootstrap repository from which merlin 
       *   system jar files have been resolved
  -    * @param args the set of command line arguments 
  +    * @param map the set of kernel context parameters 
       */
       public DefaultLoader( final Repository repository, Map map ) 
         throws Exception
  
  
  
  1.4       +2 -2      avalon/merlin/kernel/plugin/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/plugin/project.xml,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- project.xml	7 Oct 2003 17:44:10 -0000	1.3
  +++ project.xml	13 Oct 2003 01:28:26 -0000	1.4
  @@ -30,12 +30,12 @@
       <dependency>
         <groupId>merlin</groupId>
         <artifactId>merlin-kernel-spi</artifactId>
  -      <version>3.1b1</version>
  +      <version>3.1b2</version>
       </dependency>
       <dependency>
         <groupId>merlin</groupId>
         <artifactId>merlin-kernel-impl</artifactId>
  -      <version>3.1b1</version>
  +      <version>3.1b2</version>
       </dependency>
   
       <dependency>
  
  
  
  1.4       +1 -1      avalon/merlin/kernel/spi/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/spi/project.xml,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- project.xml	12 Oct 2003 17:12:45 -0000	1.3
  +++ project.xml	13 Oct 2003 01:28:26 -0000	1.4
  @@ -9,7 +9,7 @@
     <name>Merlin Kernel SPI</name>
     <package>org.apache.avalon.merlin</package>
   
  -  <currentVersion>3.1b1</currentVersion>
  +  <currentVersion>3.1b2</currentVersion>
     <inceptionYear>2002</inceptionYear>
     <shortDescription>Merlin Kernel SPI</shortDescription>
     <description>
  
  
  
  1.4       +8 -1      avalon/merlin/kernel/spi/src/java/org/apache/avalon/merlin/kernel/Kernel.java
  
  Index: Kernel.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/spi/src/java/org/apache/avalon/merlin/kernel/Kernel.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Kernel.java	12 Oct 2003 17:12:45 -0000	1.3
  +++ Kernel.java	13 Oct 2003 01:28:26 -0000	1.4
  @@ -52,6 +52,7 @@
   
   import org.apache.avalon.activation.appliance.Block;
   import org.apache.avalon.composition.model.ContainmentModel;
  +import org.apache.avalon.framework.logger.Logger;
   
   /**
    * A Kernel is the root of a containment solution. This interfaces 
  @@ -81,4 +82,10 @@
       */
       Block getRootBlock();
   
  +   /**
  +    * Return the Logger for the specified category.
  +    * @param category the category path
  +    * @return the logging channel
  +    */
  +    Logger getLoggerForCategory( final String category );
   }
  
  
  
  1.3       +2 -13     avalon/merlin/kernel/unit/maven.xml
  
  Index: maven.xml
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/unit/maven.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- maven.xml	11 Oct 2003 22:13:07 -0000	1.2
  +++ maven.xml	13 Oct 2003 01:28:26 -0000	1.3
  @@ -1,15 +1,14 @@
   <project default="jar:install" xmlns:maven="jelly:maven" xmlns:j="jelly:core" xmlns:util="jelly:util" xmlns:ant="jelly:ant">
   
     <ant:property name="maven.jar.manifest.extensions.add" value="false"/>
  -  <ant:property file="${basedir}/../../version.properties"/>
   
     <preGoal name="jar:jar">
       <maven:snapshot project="${pom}"/>
       <j:set var="timestamp" value="${snapshotSignature.substring(pom.artifactId.length)}"/>
       <ant:property name="merlin.timestamp" value="${timestamp}"/>
  -<ant:echo file="${basedir}/snapshot.properties">
  +    <ant:echo file="${basedir}/snapshot.properties">
   build.signature = ${snapshotSignature}
  -</ant:echo>
  +    </ant:echo>
       <j:forEach var="dep" items="${pom.dependencies}">
         <j:if test="${dep.getId() != 'junit:junit'}">
           <unzip src="${pom.getDependencyPath( dep.getId() )}" 
  @@ -17,15 +16,5 @@
         </j:if>
       </j:forEach>
     </preGoal>
  -
  -  <goal name="build" prereqs="jar:install">
  -    <ant:property environment="env"/>
  -    <ant:property name="merlinEnvironment" value="${env.MERLIN_HOME}"/>
  -    <j:if test="${merlinEnvironment != ''}">
  -       <ant:property name="merlin.home" value="${merlinEnvironment}"/>
  -    </j:if>
  -    <ant:property name="merlin.home" value="${user.home}/.merlin"/>
  -    <copy toDir="${merlin.home}/bin/lib" file="${maven.build.dir}/${maven.final.name}.jar"/>
  -  </goal>
   
   </project>
  
  
  
  1.5       +23 -118   avalon/merlin/kernel/unit/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/unit/project.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- project.xml	11 Oct 2003 22:13:07 -0000	1.4
  +++ project.xml	13 Oct 2003 01:28:26 -0000	1.5
  @@ -5,32 +5,21 @@
     <extend>${basedir}/../../project.xml</extend>
     <groupId>merlin</groupId>
     <id>merlin-unit</id>
  -  <name>Merlin Unit Test</name>
  -  <currentVersion>dev-031012</currentVersion>
  -  <package>*</package>
  +  <name>Merlin Unit</name>
  +  <currentVersion>dev-0001</currentVersion>
  +  <package>org.apache.avalon.merlin.unit</package>
   
     <inceptionYear>2003</inceptionYear>
  -  <shortDescription>Merlin Unit Test.</shortDescription>
  +  <shortDescription>Merlin Unit.</shortDescription>
   
     <description>
  -    Anstract unit test class.
  +  Utility package that loads a merlin kernel based on a local 
  +  repository.
     </description>
     
     <dependencies>
   
       <dependency>
  -      <groupId>avalon-framework</groupId>
  -      <artifactId>avalon-framework-api</artifactId>
  -      <version>4.1.5</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>avalon-framework</groupId>
  -      <artifactId>avalon-framework-impl</artifactId>
  -      <version>4.1.5</version>
  -    </dependency>
  -
  -
  -    <dependency>
         <groupId>avalon-repository</groupId>
         <artifactId>avalon-repository-spi</artifactId>
         <version>1.0b1</version>
  @@ -42,14 +31,15 @@
       </dependency>
   
       <dependency>
  -      <groupId>merlin</groupId>
  -      <artifactId>merlin-kernel-spi</artifactId>
  -      <version>3.1b1</version>
  +      <groupId>avalon-framework</groupId>
  +      <artifactId>avalon-framework-api</artifactId>
  +      <version>4.1.5</version>
       </dependency>
  +
       <dependency>
  -      <groupId>merlin</groupId>
  -      <artifactId>merlin-kernel-impl</artifactId>
  -      <version>3.1b1</version>
  +      <groupId>avalon-meta</groupId>
  +      <artifactId>avalon-meta-api</artifactId>
  +      <version>1.1</version>
       </dependency>
   
       <dependency>
  @@ -57,112 +47,23 @@
         <artifactId>avalon-composition-api</artifactId>
         <version>1.0b1</version>
       </dependency>
  -    <dependency>
  -      <groupId>avalon-composition</groupId>
  -      <artifactId>avalon-composition-spi</artifactId>
  -      <version>1.0b1</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>avalon-composition</groupId>
  -      <artifactId>avalon-composition-impl</artifactId>
  -      <version>1.0b1</version>
  -    </dependency>
   
       <dependency>
         <groupId>avalon-activation</groupId>
         <artifactId>avalon-activation-api</artifactId>
         <version>1.0b1</version>
       </dependency>
  -    <dependency>
  -      <groupId>avalon-activation</groupId>
  -      <artifactId>avalon-activation-spi</artifactId>
  -      <version>1.0b1</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>avalon-activation</groupId>
  -      <artifactId>avalon-activation-impl</artifactId>
  -      <version>1.0b2</version>
  -    </dependency>
   
       <dependency>
  -      <groupId>avalon-extension</groupId>
  -      <artifactId>avalon-extension-spi</artifactId>
  -      <version>1.0</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>avalon-extension</groupId>
  -      <artifactId>avalon-extension-impl</artifactId>
  -      <version>1.0</version>
  -    </dependency>
  -
  -    <dependency>
  -      <groupId>avalon-meta</groupId>
  -      <artifactId>avalon-meta-api</artifactId>
  -      <version>1.1</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>avalon-meta</groupId>
  -      <artifactId>avalon-meta-spi</artifactId>
  -      <version>1.1</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>avalon-meta</groupId>
  -      <artifactId>avalon-meta-impl</artifactId>
  -      <version>1.1</version>
  -    </dependency>
  -
  -    <dependency>
  -      <id>logkit</id>
  -      <version>1.2</version>
  +      <groupId>merlin</groupId>
  +      <artifactId>merlin-kernel-spi</artifactId>
  +      <version>3.1b2</version>
       </dependency>
   
       <dependency>
  -      <groupId>excalibur-lifecycle</groupId>
  -      <artifactId>excalibur-lifecycle-api</artifactId>
  -      <version>1.0</version>
  -    </dependency>
  -    <dependency>
  -      <id>excalibur-i18n</id>
  -      <version>1.1</version>
  -    </dependency>
  -    <dependency>
  -      <id>excalibur-thread</id>
  -      <version>1.1.1</version>
  -    </dependency>    
  -    <dependency>
  -      <id>excalibur-event</id>
  -      <version>1.0.3</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>excalibur</groupId>
  -      <artifactId>excalibur-util-concurrent</artifactId>
  -      <version>1.3.1</version>
  -    </dependency>
  -    <dependency>
  -      <id>excalibur-configuration</id>
  -      <version>1.1</version>
  -    </dependency>
  -    
  -    <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>3.8.1</version>
  -      <properties>
  -        <classloader>root</classloader>
  -      </properties>
  -    </dependency>
  -
  -    <!-- mx4j dependecies -->
  -
  -    <dependency>
  -      <groupId>mx4j</groupId>
  -      <artifactId>mx4j-jmx</artifactId>
  -      <version>1.1.1</version>
  -    </dependency>
  -    <dependency>
  -      <groupId>mx4j</groupId>
  -      <artifactId>mx4j-tools</artifactId>
  -      <version>1.1.1</version>
       </dependency>
   
     </dependencies>
  @@ -178,7 +79,7 @@
           <include>**/*TestCase.*</include>
         </includes>
         <excludes>
  -        <include>**/Abstract*.*</include>
  +        <exclude>**/Abstract*.*</exclude>
         </excludes>
         <resources>
           <resource>
  @@ -197,9 +98,13 @@
         </resources>
       </unitTest>
   
  -    <integrationUnitTestPatterns></integrationUnitTestPatterns>
  -
       <resources>
  +      <resource>
  +        <directory>${basedir}/src/etc</directory>
  +        <includes> 
  +          <include>merlin.properties</include>
  +        </includes>
  +      </resource>
         <resource>
           <directory>${basedir}</directory>
           <includes> 
  
  
  
  1.1                  avalon/merlin/kernel/unit/src/etc/merlin.properties
  
  Index: merlin.properties
  ===================================================================
  
  #
  # the bootstrap kernel loader class
  #
  merlin.bootstrap.class=org.apache.avalon.merlin.kernel.impl.CLIKernelLoader
  
  #
  # the api classpath
  #
  merlin.api.classpath.0=avalon-framework:avalon-framework-api;4.1.5
  merlin.api.classpath.1=avalon-meta:avalon-meta-api;1.1
  merlin.api.classpath.2=avalon-composition:avalon-composition-api;1.0b1
  merlin.api.classpath.3=avalon-activation:avalon-activation-api;1.0b1
  merlin.api.classpath.4=excalibur-lifecycle:excalibur-lifecycle-api;1.0
  merlin.api.classpath.5=merlin:merlin-kernel-spi;3.1b2
  
  #
  # the spi classpath
  #
  merlin.spi.classpath.0=avalon-meta:avalon-meta-spi;1.1
  merlin.spi.classpath.1=avalon-extension:avalon-extension-spi;1.0
  merlin.spi.classpath.2=avalon-composition:avalon-composition-spi;1.0b1
  merlin.spi.classpath.3=avalon-activation:avalon-activation-spi;1.0b1
  merlin.spi.classpath.4=avalon-repository:avalon-repository-spi;1.0b1
  
  #
  # the bootstrap classpath
  #
  merlin.impl.classpath.0=avalon-framework:avalon-framework-impl;4.1.5
  merlin.impl.classpath.1=avalon-meta:avalon-meta-impl;1.1
  merlin.impl.classpath.2=avalon-extension:avalon-extension-impl;1.0
  merlin.impl.classpath.3=avalon-composition:avalon-composition-impl;1.0b1
  merlin.impl.classpath.4=avalon-activation:avalon-activation-impl;1.0b1
  merlin.impl.classpath.5=excalibur-i18n:excalibur-i18n;1.1
  merlin.impl.classpath.6=avalon-repository:avalon-repository-impl;1.0b1
  merlin.impl.classpath.7=commons-cli:commons-cli;1.0
  merlin.impl.classpath.8=merlin:merlin-kernel-impl;3.1b2
  merlin.impl.classpath.9=logkit:logkit;1.2
  merlin.impl.classpath.10=excalibur-event:excalibur-event;1.0.3
  merlin.impl.classpath.11=excalibur-configuration:excalibur-configuration;1.1
  merlin.impl.classpath.12=mx4j:mx4j-jmx;1.1.1
  merlin.impl.classpath.13=mx4j:mx4j-tools;1.1.1
  
  
  
  1.4       +111 -204  avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/AbstractMerlinTestCase.java
  
  Index: AbstractMerlinTestCase.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/AbstractMerlinTestCase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AbstractMerlinTestCase.java	11 Oct 2003 22:13:07 -0000	1.3
  +++ AbstractMerlinTestCase.java	13 Oct 2003 01:28:27 -0000	1.4
  @@ -50,39 +50,23 @@
   package org.apache.avalon.merlin.unit;
   
   import java.io.File;
  -import java.io.InputStream;
  -import java.net.URL;
  -import java.net.URLClassLoader;
  -import java.util.List;
  -import java.util.ArrayList;
  -import java.util.StringTokenizer;
  -import java.util.Properties;
   import java.util.Map;
  -import java.lang.reflect.Constructor;
  -import java.lang.reflect.Method;
  -import java.lang.reflect.InvocationTargetException;
  -
  -import org.apache.avalon.merlin.kernel.impl.DefaultKernel;
  -import org.apache.avalon.merlin.kernel.impl.DefaultKernelContext;
  -import org.apache.avalon.merlin.kernel.KernelContext;
  -import org.apache.avalon.merlin.kernel.Kernel;
  +import java.util.Hashtable;
  +import java.net.URL;
  +
   import org.apache.avalon.activation.appliance.Appliance;
   import org.apache.avalon.activation.appliance.Block;
  -import org.apache.avalon.repository.Repository;
  -import org.apache.avalon.repository.ProxyContext;
  -import org.apache.avalon.repository.impl.DefaultFileRepository;
  -import org.apache.avalon.repository.impl.DefaultAuthenticator;
  -import org.apache.avalon.composition.util.ExceptionHelper;
   import org.apache.avalon.composition.model.ContainmentModel;
   import org.apache.avalon.framework.logger.Logger;
  +import org.apache.avalon.merlin.kernel.Kernel;
  +import org.apache.avalon.merlin.unit.DefaultRunnableKernel;
   
   import junit.framework.TestCase;
   
   /**
  - * Abstract Merlin Test Case.
  + * Default loader testcase.
    *
  - * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
  - * @version $Revision$ $Date$
  + * @author mcconnell@apache.org
    */
   public class AbstractMerlinTestCase extends TestCase
   {
  @@ -96,10 +80,10 @@
       public static boolean MERLIN_INFO_ON = true;
   
       public static final File MAVEN_TARGET_CLASSES_DIR = 
  -      getTargetClassesDirectory();
  +      getProjectFile( "target/classes" );
   
       public static final File MAVEN_TARGET_TEST_CLASSES_DIR = 
  -      getTargetTestClassesDirectory();
  +      getProjectFile( "target/test-classes" );
   
       public static final File MERLIN_DEFAULT_CONFIG_FILE = 
         getProjectFile( "conf/config.xml" );
  @@ -108,16 +92,16 @@
       // state
       //-------------------------------------------------------------------
   
  -    private final KernelContext m_context;
  -
  -    private final Kernel m_kernel;
  +    private final DefaultRunnableKernel m_kernel;
   
       private final ContainmentModel m_test;
   
  -    private Block m_block;
  +    private final Thread m_thread;
   
       private Logger m_logger;
   
  +    private Block m_block;
  +
       //-------------------------------------------------------------------
       // constructors
       //-------------------------------------------------------------------
  @@ -159,16 +143,21 @@
       * Creation of a new test case instance using a supplied test container 
       * path, info and debug policies and unit test name.
       *
  -    * @param url the test container deployment path
  +    * @param block the test container deployment path
  +    * @param targets the test container deployment path
       * @param info information summary display policy
       * @param debug internal container debug policy
       * @param name the name of the test case
       */
  -    public AbstractMerlinTestCase( 
  +    public AbstractMerlinTestCase(
         File block, File targets, boolean info, boolean debug, String name )
       {
           super( name );
   
  +        //
  +        // validate arguments
  +        //
  +
           if( block == null )
           {
               throw new NullPointerException( "block" );
  @@ -188,52 +177,67 @@
               throw new IllegalStateException( error );
           }
   
  -        URL url = convertToURL( block );
  -        URL conf = convertToURL( targets );
  -
  -        File base = 
  -          new File( 
  -            System.getProperty( 
  -              "basedir", 
  -              System.getProperty( "user.dir" ) ) );
  -
  -        File repo = getSystemRepositoryDirectory();
  -        Repository repository = createBootstrapRepository( repo );
  -        File library = base;
  -        URL kernel = null;
  -        URL config = null;
  -
           //
  -        // bootstrap the kernel
  +        // build the kernel
           //
   
  +        Map map = new Hashtable();
  +        map.put( "merlin.policy.info", new Boolean( info ) );
  +        map.put( "merlin.policy.debug", new Boolean( debug ) );
  +        map.put( "merlin.repository.dir", getMavenRepositoryDirectory() );
  +
           try
           {
  -            m_context = 
  -              new DefaultKernelContext( 
  -                repository, repo, library, base, kernel, new URL[0], 
  -                config, true, info, debug );
  -            m_kernel = new DefaultKernel( m_context );
  -            m_logger = 
  -              m_context.getLoggerForCategory( "testcase" ).getChildLogger( name );
  +            m_kernel = new DefaultRunnableKernel( map );
  +            m_thread = new Thread( m_kernel );
  +            m_thread.start();
           }
           catch( Throwable e )
           {
  -            final String message =
  -              "Internal error while attempting to establish the kernel.";
  -            final String error = ExceptionHelper.packException( message, e, true );
  -            throw new UnitRuntimeException( error, e );
  +            final String error = 
  +              "Runnable kernel establishment failure.";
  +            final String msg = UnitHelper.packException( error, e, true );
  +            throw new UnitRuntimeException( msg, e );
           }
   
  -        // 
  -        // Programatically add the test container to the root containment 
  -        // model so that we get a reference to the test model enabling 
  -        // access to the test block following setup of the test case. This
  -        // allows us to directly lookup objects relative to the test container.
  +        //
  +        // wait for the kernel to initialize
  +        //
  +
  +        while( !m_kernel.established() )
  +        {
  +            try
  +            {
  +                Thread.currentThread().sleep( 100 );
  +            }
  +            catch( Throwable e )
  +            {
  +                if( m_kernel.getError() != null )
  +                {
  +                    final String message = 
  +                      "Internal error while attempting to establish the kernel.";
  +                    final String error = 
  +                      UnitHelper.packException( message, m_kernel.getError(), true );
  +                    throw new UnitRuntimeException( error, m_kernel.getError() );
  +                }
  +            }
  +        }
  +
  +        //
  +        // setup a logger for the testcase
  +        //
  +
  +        m_logger = m_kernel.getLoggerForCategory( "testase" );
  +
  +        //
  +        // add a container holding the components that will
  +        // be used as services in the testcase
           //
   
           try
           {
  +            URL url = convertToURL( block );
  +            URL conf = convertToURL( targets );
               ContainmentModel root = m_kernel.getContainmentModel();
               m_test = root.addContainmentModel( url, conf );
           }
  @@ -241,33 +245,35 @@
           {
               final String message = 
                 "Internal error while attempting to establish the test container.";
  -            final String error = ExceptionHelper.packException( message, e, true );
  -            getLogger().error( error );
  -            throw new UnitRuntimeException( error );
  +            final String error = UnitHelper.packException( message, e, true );
  +            throw new UnitRuntimeException( error, e );
           }
       }
   
  -    //-------------------------------------------------------------------
  -    // testcase
  -    //-------------------------------------------------------------------
  +    //--------------------------------------------------------
  +    // TestCase
  +    //--------------------------------------------------------
   
      /**
  -    * Startup the Merlin Kernel.
  +    * Startup the kernel based on the meta model established 
  +    * under the constructor.  The implementation will locate 
  +    * the test container and establish it as the reference for 
  +    * relative service lookups.
       */
       public void setUp() throws Exception
       {
  -        getKernel().startup();
  +        m_kernel.startup();
   
           try
           {
  -            m_block = getKernel().getBlock( m_test );
  +            m_block = m_kernel.getBlock( m_test );
           }
           catch( Throwable e )
           {
               final String message = 
                 "Internal error while attempting to resolve test block: " 
                 + m_test;
  -            final String error = ExceptionHelper.packException( message, e, true );
  +            final String error = UnitHelper.packException( message, e, true );
               getLogger().error( error );
               throw new UnitException( error );
           }
  @@ -281,17 +287,17 @@
           m_kernel.shutdown();
       }
   
  -    //-------------------------------------------------------------------
  -    // service access
  -    //-------------------------------------------------------------------
  +    //--------------------------------------------------------
  +    // utilities
  +    //--------------------------------------------------------
   
      /**
  -    * Return a reference to the kernel.
  -    * @return the kernel
  +    * Return the assigned logging channel for the test case.
  +    * @return the logging channel
       */
  -    protected Kernel getKernel()
  +    protected Logger getLogger()
       {
  -        return m_kernel;
  +        return m_logger;
       }
   
      /**
  @@ -304,7 +310,7 @@
       * @return the object resolved from an appliance defined by the supplied path
       * @exception UnitException if a resolution error occurs
       */
  -    protected Object resolve( String path ) throws UnitException
  +    protected Object resolve( String path ) throws Exception
       {
           if( path == null ) throw new NullPointerException( "path" );
   
  @@ -323,107 +329,57 @@
           {
               final String error = 
                 "Service resolution error from path: " + path;
  -            final String msg = ExceptionHelper.packException( error, e, false );
  +            final String msg = UnitHelper.packException( error, e, false );
               throw new UnitException( msg, e );
           }
       }
   
  -   /**
  -    * Return the assigned logging channel for the test case.
  -    * @return the logging channel
  -    */
  -    protected Logger getLogger()
  -    {
  -        return m_logger;
  -    }
  -
  -    //-------------------------------------------------------------------
  +    //--------------------------------------------------------
       // implementation
  -    //-------------------------------------------------------------------
  -
  -   /**
  -    * Return the repository from which we will build the kernel classloader.
  -    * @param repo the system repository directory
  -    * @return the repository
  -    */
  -    private Repository createBootstrapRepository( File repo )
  -    {
  -        ProxyContext proxy = createProxyContext();
  -        URL[] hosts = createHostsSequence();
  -        return new DefaultFileRepository( repo, proxy, hosts );
  -    }
  +    //--------------------------------------------------------
   
      /**
  -    * Return an array of hosts based on the maven.repo.remote property value.
  -    * @return the array of remote hosts
  +    * Convert a supplied file to a url.  If the file argument is
  +    * null return null else return file.toURL().  
  +    * @param file the file to convert
  +    * @return the equivalent url
       */
  -    private URL[] createHostsSequence()
  -    {
  -        ArrayList list = new ArrayList();
  -        String path = System.getProperty( "maven.repo.remote" );
  -        if( path == null ) return new URL[0];
  -
  -        StringTokenizer tokenizer = new StringTokenizer( path, "," );
  -        while( tokenizer.hasMoreElements() )
  -        {
  -            String token = tokenizer.nextToken();
  -            appendEntry( list, token );
  -        }
  -        return (URL[]) list.toArray( new URL[0] );
  -    }
  -
  -    private void appendEntry( List list, String token )
  +    private URL convertToURL( File file )
       {
  +        if( file == null ) return null;
           try
           {
  -            list.add( new URL( token ) );
  +            return file.toURL();
           }
           catch( Throwable e )
           {
               final String error = 
  -              "Unable to convert token [" + token + "] to a URL.";
  +              "Unable to convert file [" + file + "] to a url.";
               throw new UnitRuntimeException( error, e );
           }
       }
   
      /**
  -    * Create of the proxy context.  If no proxy properties are declared a null
  -    * value is returned.  Proxy values are based assessment of  
  -    * properties maven.proxy.host, maven.proxy.port, maven.proxy.username and 
  -    * maven.proxy.password.
  -    *
  -    * @return the proxy context or null if not required
  +    * Convinience method to get the ${basedir}/[path] directory.
  +    * @return the deployment url
       */
  -    private ProxyContext createProxyContext()
  +    public static File getProjectFile( String path )
       {
  -        String host = System.getProperty( "maven.proxy.host" );
  -        if( host != null )
  -        {
  -            String proxyPort = System.getProperty( "maven.proxy.port" );
  -            if( proxyPort == null ) 
  -              throw new IllegalStateException( "maven.proxy.port" );
  -            int port = new Integer( proxyPort ).intValue();
  -            String username = System.getProperty( "maven.proxy.username" );
  -            DefaultAuthenticator authenticator = null;
  -            if( username != null )
  -            {
  -                String password = System.getProperty( "maven.proxy.password" );
  -                authenticator = new DefaultAuthenticator( username, password );
  -            }
  -            return new ProxyContext( host, port, authenticator );
  -        }
  -        else
  -        {
  -            return null;
  -        }
  +        File base = getBaseDirectory();
  +        return new File( base, path );
  +    }
  +
  +    private static File getBaseDirectory()
  +    {
  +        String basedir = System.getProperty( "basedir" );
  +        return new File( basedir );
       }
   
      /**
  -    * Return the file corresponding  to the merlin system repository.
  -    *
  +    * Return the maven system repository directory.
       * @return the system repository directory
       */
  -    private static File getSystemRepositoryDirectory()
  +    private File getMavenRepositoryDirectory()
       {
           final String system = System.getProperty( "maven.repo.local" );
           if( system != null )
  @@ -442,55 +398,6 @@
                   File user = new File( System.getProperty( "user.dir" ) );
                   return new File( user, ".merlin/system" );
               }
  -        }
  -    }
  -
  -   /**
  -    * Convinience method to get the ${basedir}/target/classes directory.
  -    * @return the deployment directory
  -    */
  -    public static File getTargetClassesDirectory()
  -    {
  -        return getProjectFile( "target/classes" );
  -    }
  -
  -   /**
  -    * Convinience method to get the ${basedir}/target/test-classes directory.
  -    * @return the deployment url
  -    */
  -    public static File getTargetTestClassesDirectory()
  -    {
  -        return getProjectFile( "target/test-classes" );
  -    }
  -
  -   /**
  -    * Convinience method to get the ${basedir}/[path] directory.
  -    * @return the deployment url
  -    */
  -    public static File getProjectFile( String path )
  -    {
  -        File base = getBaseDirectory();
  -        return new File( base, path );
  -    }
  -
  -    private static File getBaseDirectory()
  -    {
  -        String basedir = System.getProperty( "basedir" );
  -        return new File( basedir );
  -    }
  -
  -    private URL convertToURL( File file )
  -    {
  -        if( file == null ) return null;
  -        try
  -        {
  -            return file.toURL();
  -        }
  -        catch( Throwable e )
  -        {
  -            final String error = 
  -              "Unable to convert file [" + file + "] to a url.";
  -            throw new UnitRuntimeException( error, e );
           }
       }
   }
  
  
  
  1.2       +73 -56    avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/UnitException.java
  
  Index: UnitException.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/UnitException.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- UnitException.java	7 Oct 2003 18:03:11 -0000	1.1
  +++ UnitException.java	13 Oct 2003 01:28:27 -0000	1.2
  @@ -1,66 +1,73 @@
  -/*
  -
  - ============================================================================
  -                   The Apache Software License, Version 1.1
  - ============================================================================
  -
  - Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  -
  - Redistribution and use in source and binary forms, with or without modifica-
  - tion, 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 "Jakarta", "Apache Avalon", "Avalon Framework" 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 (INCLU-
  - DING, 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/>.
  -
  -*/
  +/* ====================================================================
  + * The Apache Software License, Version 1.1
  + *
  + * Copyright (c) 1997-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 "Jakarta", "Avalon", 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.merlin.unit;
   
  -import org.apache.avalon.framework.CascadingException;
  -
   /**
  - * Exception to indicate that there was an error relating to unit execution.
  + * Exception thrown in response to a load failure.
    *
    * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
  - * @version $Revision$ $Date$
  + * @version CVS $Revision$ $Date$
    */
   public class UnitException
  -    extends CascadingException
  +    extends Exception
   {
  +    /**
  +     * The Throwable that caused this exception to be thrown.
  +     */
  +    private final Throwable m_throwable;
   
       /**
        * Construct a new <code>UnitException</code> instance.
  @@ -80,7 +87,17 @@
        */
       public UnitException( final String message, final Throwable throwable )
       {
  -        super( message, throwable );
  +        super( message );
  +        m_throwable = throwable;
       }
  -}
   
  +    /**
  +     * Retrieve root cause of the exception.
  +     *
  +     * @return the root cause
  +     */
  +    public final Throwable getCause()
  +    {
  +        return m_throwable;
  +    }
  +}
  
  
  
  1.2       +67 -62    avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/UnitRuntimeException.java
  
  Index: UnitRuntimeException.java
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/UnitRuntimeException.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- UnitRuntimeException.java	7 Oct 2003 18:03:11 -0000	1.1
  +++ UnitRuntimeException.java	13 Oct 2003 01:28:27 -0000	1.2
  @@ -1,86 +1,91 @@
  -/*
  -
  - ============================================================================
  -                   The Apache Software License, Version 1.1
  - ============================================================================
  -
  - Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  -
  - Redistribution and use in source and binary forms, with or without modifica-
  - tion, 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 "Jakarta", "Apache Avalon", "Avalon Framework" 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 (INCLU-
  - DING, 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/>.
  -
  -*/
  +/* ====================================================================
  + * The Apache Software License, Version 1.1
  + *
  + * Copyright (c) 1997-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 "Jakarta", "Avalon", 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.merlin.unit;
   
  -import org.apache.avalon.framework.CascadingRuntimeException;
  -
   /**
  - * Exception to indicate that there was an error relating to unit execution.
  + * Class from which all exceptions should inherit.
  + * Allows recording of nested exceptions.
    *
    * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
  - * @version $Revision$ $Date$
  + * @version CVS $Revision$ $Date$
    */
   public class UnitRuntimeException
  -    extends CascadingRuntimeException
  +    extends RuntimeException
   {
  +    private final Throwable m_throwable;
   
       /**
        * Construct a new <code>UnitRuntimeException</code> instance.
        *
        * @param message The detail message for this exception.
  +     * @param throwable the root cause of the exception
        */
  -    public UnitRuntimeException( final String message )
  +    public UnitRuntimeException( final String message, final Throwable throwable )
       {
  -        this( message, null );
  +        super( message );
  +        m_throwable = throwable;
       }
   
       /**
  -     * Construct a new <code>UnitRuntimeException</code> instance.
  +     * Retrieve root cause of the exception.
        *
  -     * @param message The detail message for this exception.
  -     * @param throwable the root cause of the exception
  +     * @return the root cause
        */
  -    public UnitRuntimeException( final String message, final Throwable throwable )
  +    public final Throwable getCause()
       {
  -        super( message, throwable );
  +        return m_throwable;
       }
   }
  -
  
  
  
  1.2       +1 -25     avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/package.html
  
  Index: package.html
  ===================================================================
  RCS file: /home/cvs/avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/package.html,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- package.html	7 Oct 2003 18:03:11 -0000	1.1
  +++ package.html	13 Oct 2003 01:28:27 -0000	1.2
  @@ -1,31 +1,7 @@
   
   <body>
   <p>
  -The unit package is an extended UnitTest class that handles the establishment of 
  -a Merlin Kernel using the target/classes as the primary deployment path.  The 
  -unit test builds and deploys the container and provides convinient access to 
  -services via component paths.
  +Pending.
   </p>
  -<h3>Usage Example</h3>
  -<p>The package include the class AbstractMerlinTestCase.  To create a new test
  -case including the Merlin service handling simply extend AbstractMerlinTestCase.</p>
  -<pre>
  -  public class SampleTestCase extends AbstractMerlinTestCase
  -  {
  -      public void testSomething()
  -      {
  -          // resolve a service established by Merlin
  -          Hello hello = resolve( "hello" );
  -
  -          // do some tests against the Hello service
  -          assetTrue( hello.getMessage().equals( "Hello" ) );
  -      }
  -  }
  -</pre>
  -<p>In the above example the abstract testcase is establishing a merlin kernel and 
  -loading a container relative to the default deployment path ${basedir}/target/classes.
  -You can override default behaviour by using constructor arguments to qualify an 
  -alternative deployment path, info, and debugging policies.</p>
  -
   </body>
   
  
  
  
  1.1                  avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/DefaultRunnableKernel.java
  
  Index: DefaultRunnableKernel.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 2002-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, 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 "Jakarta", "Apache Avalon", "Avalon Framework" 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 (INCLU-
   DING, 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.merlin.unit;
  
  import java.io.File;
  import java.io.InputStream;
  import java.net.URL;
  import java.net.URLClassLoader;
  import java.util.ArrayList;
  import java.util.StringTokenizer;
  import java.util.Properties;
  import java.util.Hashtable;
  import java.util.Map;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationTargetException;
  
  import org.apache.avalon.activation.appliance.Block;
  import org.apache.avalon.composition.model.ContainmentModel;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.merlin.kernel.Kernel;
  import org.apache.avalon.merlin.kernel.KernelException;
  import org.apache.avalon.repository.Repository;
  import org.apache.avalon.repository.ProxyContext;
  import org.apache.avalon.repository.impl.DefaultFileRepository;
  import org.apache.avalon.repository.impl.DefaultAuthenticator;
  
  /**
   * Merlin kernel bootstrap.
   *
   * @author mcconnell@apache.org
   */
  public class DefaultRunnableKernel implements Runnable, Kernel
  {
      //--------------------------------------------------------
      // static
      //--------------------------------------------------------
  
      private static final String MERLIN_PROPERTIES_NAME = 
        "merlin.properties";
  
      private static final String MERLIN_API_CLASSPATH_KEY = 
        "merlin.api.classpath";
  
      private static final String MERLIN_SPI_CLASSPATH_KEY = 
        "merlin.spi.classpath";
  
      private static final String MERLIN_IMPL_CLASSPATH_KEY = 
        "merlin.impl.classpath";
  
      private static final String MERLIN_LOADER_CLASS =
        "org.apache.avalon.merlin.kernel.impl.DefaultLoader";
  
      private static final String STARTUP = "startup";
      private static final String SHUTDOWN = "shutdown";
      private static final String CONTINUE = "continue";
      private static final String EXIT = "exit";
  
      //--------------------------------------------------------
      // state
      //--------------------------------------------------------
  
      private final ClassLoader m_classloader;
      private final Map m_map;
      private Repository m_repository;
      private Object m_loader;
      private String m_command = CONTINUE;
      private Throwable m_error;
      private Kernel m_kernel;
  
      private boolean m_started = false;
  
      //--------------------------------------------------------
      // constructors
      //--------------------------------------------------------
  
     /**
      * Creation of a new kernel loader.
      */
      public DefaultRunnableKernel( Map map )
      {
          m_map = map;
  
          try
          {
              m_repository = createBootstrapRepository();
              Properties properties = loadBootstrapProperties();
              ClassLoader current = Thread.currentThread().getContextClassLoader();
              m_classloader = createClassLoader( current, m_repository, properties );
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to build the loader.";
              throw new UnitRuntimeException( error, e );
          }
      }
  
      public void run()
      {
          Thread.currentThread().setContextClassLoader( m_classloader );
  
          //
          // bootstrap the kernel loader
          //
  
          try
          {
              Class clazz = getLoaderClass();
              Constructor constructor = 
                clazz.getConstructor( new Class[]{ Repository.class, Map.class } );
              m_loader = constructor.newInstance( new Object[] { m_repository, m_map } );
  
              Method method = 
                clazz.getMethod( "getKernel", new Class[0] );
              m_kernel = (Kernel) method.invoke( m_loader, new Object[0] );
              m_started = true;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to construct the kernel loader.";
              throw new UnitRuntimeException( error, e );
          }
  
          while( m_command != EXIT )
          {
              if( m_command == STARTUP )
              {
                  handleStartup();
              }
              else if( m_command == SHUTDOWN )
              {
                  handleShutdown();
              }
              else
              {
                  try
                  {
                      Thread.currentThread().sleep( 100 );
                  }
                  catch( Throwable e )
                  {
                      // wakeup
                  }
              }
          }
      }
  
      public boolean established()
      {
          return m_started;
      }
  
      public Throwable getError()
      {
          return m_error;
      }
  
      //--------------------------------------------------------
      // Kernel
      //--------------------------------------------------------
  
     /**
      * Return the root containment model.
      * @return the containment model
      */
      public ContainmentModel getContainmentModel()
      {
          return m_kernel.getContainmentModel();
      }
  
     /**
      * Return the block matching the supplied model.
      * @return the containment block
      */
      public Block getBlock( ContainmentModel model ) throws KernelException
      {
          return m_kernel.getBlock( model );
      }
  
     /**
      * Return the root block.
      * @return the containment block
      */
      public Block getRootBlock()
      {
          return m_kernel.getRootBlock();
      }
  
      public void startup()
      {
          synchronized( m_command )
          {
              m_command = STARTUP;
              while( m_command.equals( STARTUP ) )
              {
                  try
                  {
                      Thread.currentThread().sleep( 100 );
                  }
                  catch( Throwable e )
                  {
                      // wakeup
                  }
              }
              if( m_error != null )
              {
                  final String error = 
                    "Startup failure due to kernel error.";
                  throw new UnitRuntimeException( error, m_error );
              }
          }
      }
  
      public void shutdown()
      {
          if( m_error != null ) return;
          synchronized( m_command )
          {
              m_command = SHUTDOWN;
              while( m_command.equals( SHUTDOWN ) )
              {
                  try
                  {
                      Thread.currentThread().sleep( 100 );
                  }
                  catch( Throwable e )
                  {
                      // wakeup
                  }
              }
          }
      }
  
     /**
      * Return the Logger for the specified category.
      * @param category the category path
      * @return the logging channel
      */
      public Logger getLoggerForCategory( final String category )
      {
          return m_kernel.getLoggerForCategory( category );
      }
  
      //--------------------------------------------------------
      // implementation
      //--------------------------------------------------------
  
      private void handleStartup()
      {
          try
          {
              Class clazz = getLoaderClass();
              Method method = 
                clazz.getMethod( STARTUP, new Class[0] );
              method.invoke( m_loader, new Object[0] );
              m_command = CONTINUE;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to start the kernel.";
              m_error = new UnitRuntimeException( error, e );
              m_command = EXIT;
          }
      }
  
      private void handleShutdown()
      {
          try
          {
              Class clazz = getLoaderClass();
              Method method = 
                clazz.getMethod( SHUTDOWN, new Class[]{} );
              method.invoke( m_loader, new Class[0] );
              m_command = EXIT;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to shutdown the kernel.";
              m_error = new UnitRuntimeException( error, e );
              m_command = EXIT;
          }
      }
  
      private Class getLoaderClass()
      {
          try
          {
              return m_classloader.loadClass( MERLIN_LOADER_CLASS );
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to load the kernel loader class.";
              throw new UnitRuntimeException( error, e );
          }
      }
  
     /**
      * Create the classloader holding the kernel.
      */
      private ClassLoader createClassLoader( 
         ClassLoader loader, Repository repository, Properties properties ) throws Exception
      {
          URL[] api = getURLs( repository, properties, MERLIN_API_CLASSPATH_KEY );
          URL[] spi = getURLs( repository, properties, MERLIN_SPI_CLASSPATH_KEY );
          URL[] impl = getURLs( repository, properties, MERLIN_IMPL_CLASSPATH_KEY );
  
          ClassLoader apiLoader = new URLClassLoader( api, loader );
          ClassLoader spiLoader = new URLClassLoader( spi, apiLoader );
          ClassLoader implLoader = new URLClassLoader( impl, spiLoader );
          return implLoader;
      }
  
     /**
      * Load the bootstrap properties.
      */
      private Properties loadBootstrapProperties()
      {
          try
          {
              ClassLoader classloader = Thread.currentThread().getContextClassLoader();
              InputStream input = 
                classloader.getResourceAsStream( MERLIN_PROPERTIES_NAME  );
              Properties properties = new Properties();
              properties.load( input );
              return properties;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to create the load bootstrap properties.";
              throw new UnitRuntimeException( error, e );
          }
      }
  
     /**
      * Return the repository from which we will build the kernel classloader.
      *
      * @return the repository
      */
      private Repository createBootstrapRepository() 
      {
          try
          {
              File repo = getSystemRepositoryDirectory();
              ProxyContext proxy = createProxyContext();
              URL[] hosts = createHostsSequence();
              return new DefaultFileRepository( repo, proxy, hosts );
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while attempting to create the bootstrap repository.";
              throw new UnitRuntimeException( error, e );
          }
      }
  
     /**
      * Return an array of hosts based on the maven.repo.remote property value.
      * @return the array of remote hosts
      */
      private URL[] createHostsSequence() throws Exception
      {
          ArrayList list = new ArrayList();
          String path = System.getProperty( "maven.repo.remote" );
          if( path == null ) return new URL[0];
  
          StringTokenizer tokenizer = new StringTokenizer( path, "," );
          while( tokenizer.hasMoreElements() )
          {
              String token = tokenizer.nextToken();
              list.add( new URL( token ) );
          }
          return (URL[]) list.toArray( new URL[0] );
      }
  
     /**
      * Create of the proxy context.  If no proxy properties are declared a null
      * value is returned.  Proxy values are based assessment of  
      * properties maven.proxy.host, maven.proxy.port, maven.proxy.username and 
      * maven.proxy.password.
      *
      * @return the proxy context or null if not required
      */
      private ProxyContext createProxyContext()
      {
          String host = System.getProperty( "maven.proxy.host" );
          if( host != null )
          {
              String proxyPort = System.getProperty( "maven.proxy.port" );
              if( proxyPort == null ) throw new IllegalStateException( "maven.proxy.port" );
              int port = new Integer( proxyPort ).intValue();
              String username = System.getProperty( "maven.proxy.username" );
              DefaultAuthenticator authenticator = null;
              if( username != null )
              {
                  String password = System.getProperty( "maven.proxy.password" );
                  authenticator = new DefaultAuthenticator( username, password );
              }
              return new ProxyContext( host, port, authenticator );
          }
          else
          {
              return null;
          }
      }
  
     /**
      * Return the file corresponding  to the merlin system repository.
      *
      * @return the system repository directory
      */
      public static File getSystemRepositoryDirectory()
      {
          final String system = System.getProperty( "maven.repo.local" );
          if( system != null )
          {
              return new File( new File( system ), "repository" );
          }
          else
          {
              final String home = System.getProperty( "maven.home" );
              if( home != null )
              {
                  return new File( new File( home ), "repository" );
              }
              else
              {
                  File user = new File( System.getProperty( "user.dir" ) );
                  return new File( user, ".merlin/system" );
              }
          }
      }
  
     /**
      * Consruct an array of URLs based on the declarations provided
      * in the supplied properties object.  Each URL is specified 
      * as a property value is mapped to a numbered property key in 
      * the form [key].n.  Each value is expressed as a repository
      * entry in the form [group]:[artifact];[version]. 
      * 
      * @param repository the repository from which artifacts shall be
      *   cached
      * @param properties the properties holding the keyed artifact ids
      * @param key the property name key
      * @return the array of urls
      */ 
      private static URL[] getURLs( 
         Repository repository, Properties properties, String key )
      {
          int i = 0;
          ArrayList list = new ArrayList();
          String label = getProperty( properties, key, i );
          while( label != null )
          {
              i++;
              list.add( getURL( repository, label ) );
              label = getProperty( properties, key, i );
          }
          return (URL[]) list.toArray( new URL[0] );
      }
  
     /**
      * Return a property key by concatonation of the supplied
      * key, the period character and an integer.
      * @param prioperties the properties set containing the keyed entry
      * @param key the partial key
      * @param i the key index
      * @return the value of the property [key].[i]
      */
      private static String getProperty( Properties properties, String key, int i )
      {
           final String label = key + "." + i;
           return properties.getProperty( label );
      }
  
     /**
      * Return a URL a a local repository cached resource replative to 
      * a suplied property value in the form [group]:[artifact];[version].
      * @param repository the repository under whcih resources are cached
      * @param item the encoded artifact identifier
      * @return the URL to the locally cached artifact
      */ 
      private static URL getURL( Repository repository, String item )
      {
           try
           {
               int n = item.indexOf( ":" );
               final String group = item.substring( 0, n );
              
               String artifact = null;
               String version = null;
               int m = item.indexOf( ";" );
               if( m > -1 )
               {
                   artifact = item.substring( n+1, m );
                   version = item.substring( m+1, item.length() );
               }
               else
               {
                   artifact = item.substring( n+1, item.length() );
               }
              
               return repository.getArtifact( group, artifact, version, "jar" );
           }
           catch( Throwable e )
           {
               final String error = 
                "Internal bootstrap error.  Unable to load item: " + item;
               throw new UnitRuntimeException( error, e );
           }
      }
  }
  
  
  
  
  1.1                  avalon/merlin/kernel/unit/src/java/org/apache/avalon/merlin/unit/UnitHelper.java
  
  Index: UnitHelper.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, 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 "Jakarta", "Apache Avalon", "Avalon Framework" 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 (INCLU-
   DING, 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.merlin.unit;
  
  import java.io.PrintWriter;
  import java.io.StringWriter;
  import java.lang.reflect.Method;
  import java.util.StringTokenizer;
  
  /**
   * General utilities supporting the packaging of exception messages.
   * @author <a href="mailto:mcconnell@osm.net">Stephen McConnell</a>
   */
  public class UnitHelper
  {
      private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
  
      /**
       * Returns the exception and causal exceptions as a formatted string.
       * @param message the header message
       * @param e the exception
       * @return String the formatting string
       */
      public static String packException( final String message, final Throwable e )
      {
          return packException( message, e, true );
      }
  
      /**
       * Returns the exception and causal exceptions as a formatted string.
       * @param message the header message
       * @param e the exception
       * @return String the formatting string
       */
      public static String packException( 
         final String message, final Throwable e, boolean stack )
      {
          StringBuffer buffer = new StringBuffer();
          buffer.append( message );
          if( e == null )
          {
              return buffer.toString();
          } else
          {
              buffer.append( "\n" );
              buffer.append( 
  "-------------------------------------------------------------------" );
              buffer.append( "\nException: " + e.getClass().getName() );
              buffer.append( "\nMessage: " + e.getMessage() );
              packCause( buffer, getCause( e ) ).toString();
          }
          Throwable root = getLastThrowable( e );
          if( (root != null) && stack )
          {
              buffer.append( 
  "\n\n---- stack trace --------------------------------------------------" );
              String[] trace = captureStackTrace( root );
              for( int i = 0; i < trace.length; i++ )
              {
                  buffer.append( "\n" + trace[i] );
              }
          }
          buffer.append( 
  "\n-------------------------------------------------------------------" );
          return buffer.toString();
      }
  
      private static StringBuffer packCause( StringBuffer buffer, Throwable cause )
      {
          if( cause == null )
          {
              return buffer;
          }
          buffer.append( "\n\nCause: " + cause.getClass().getName() );
          buffer.append( "\nMessage: " + cause.getMessage() );
          return packCause( buffer, getCause( cause ) );
      }
  
      private static Throwable getLastThrowable( Throwable exception )
      {
          Throwable cause = getCause( exception );
          if( cause != null )
          {
              return getLastThrowable( cause );
          }
          return exception;
      }
  
      private static Throwable getCause( Throwable exception )
      {
          if( exception == null )
          {
              throw new NullPointerException( "exception" );
          }
  
          try
          {
              Method method = exception.getClass().getMethod( "getCause", new Class[0] );
              return (Throwable) method.invoke( exception, new Object[0] );
          } catch( Throwable e )
          {
              return null;
          }
      }
  
      /**
       * Captures the stack trace associated with this exception.
       *
       * @param throwable a <code>Throwable</code>
       * @return an array of Strings describing stack frames.
       */
      private static String[] captureStackTrace( final Throwable throwable )
      {
          final StringWriter sw = new StringWriter();
          throwable.printStackTrace( new PrintWriter( sw, true ) );
          return splitString( sw.toString(), LINE_SEPARATOR );
      }
  
      /**
       * Splits the string on every token into an array of stack frames.
       *
       * @param string the string to split
       * @param onToken the token to split on
       * @return the resultant array
       */
      private static String[] splitString( final String string, final String onToken )
      {
          final StringTokenizer tokenizer = new StringTokenizer( string, onToken );
          final String[] result = new String[tokenizer.countTokens()];
  
          for( int i = 0; i < result.length; i++ )
          {
              result[i] = tokenizer.nextToken();
          }
  
          return result;
      }
  
      private static void printCause( java.io.PrintStream out, Throwable e )
      {
          Throwable cause = getCause( e );
          out.println( "Cause: " + cause.toString() );
          if( getCause( cause ) != null )
          {
              printCause( out, cause );
          }
      }
  }
  
  
  

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