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/component/src/java/org/apache/avalon/excalibur/testcase BufferedLogger.java CascadingAssertionFailedError.java ComponentStateValidator.java ExcaliburTestCase.java FullLifecycleComponent.java LatchedThreadGroup.java
Date Fri, 07 Mar 2003 19:34:32 GMT
bloritsch    2003/03/07 11:34:32

  Added:       component/src/java/org/apache/avalon/excalibur/testcase
                        BufferedLogger.java
                        CascadingAssertionFailedError.java
                        ComponentStateValidator.java ExcaliburTestCase.java
                        FullLifecycleComponent.java LatchedThreadGroup.java
  Log:
  merge testcase into component
  
  Revision  Changes    Path
  1.1                  avalon-excalibur/component/src/java/org/apache/avalon/excalibur/testcase/BufferedLogger.java
  
  Index: BufferedLogger.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.testcase;
  
  import org.apache.avalon.framework.ExceptionUtil;
  import org.apache.avalon.framework.logger.Logger;
  
  /**
   * Simple Logger which logs all information to an internal StringBuffer.
   *  When logging is complete call toString() on the logger to obtain the
   *  logged output.  Useful for testing.
   *
   * @author <a href="mailto:leif@tanukisoftware.com">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2003/03/07 19:34:31 $
   * @since 4.0
   */
  public class BufferedLogger
      implements Logger
  {
      private final StringBuffer m_sb = new StringBuffer();
  
      /**
       * Log a debug message.
       *
       * @param message the message
       */
      public void debug( final String message )
      {
          debug( message, null );
      }
  
      /**
       * Log a debug message.
       *
       * @param message the message
       * @param throwable the throwable
       */
      public void debug( final String message, final Throwable throwable )
      {
          append( "DEBUG", message, throwable );
      }
  
      /**
       * Determine if messages of priority "debug" will be logged.
       *
       * @return true if "debug" messages will be logged
       */
      public boolean isDebugEnabled()
      {
          return true;
      }
  
      /**
       * Log a info message.
       *
       * @param message the message
       */
      public void info( final String message )
      {
          info( message, null );
      }
  
      /**
       * Log a info message.
       *
       * @param message the message
       * @param throwable the throwable
       */
      public void info( final String message, final Throwable throwable )
      {
          append( "INFO", message, throwable );
      }
  
      /**
       * Determine if messages of priority "info" will be logged.
       *
       * @return true if "info" messages will be logged
       */
      public boolean isInfoEnabled()
      {
          return true;
      }
  
      /**
       * Log a warn message.
       *
       * @param message the message
       */
      public void warn( final String message )
      {
          warn( message, null );
      }
  
      /**
       * Log a warn message.
       *
       * @param message the message
       * @param throwable the throwable
       */
      public void warn( final String message, final Throwable throwable )
      {
          append( "WARN", message, throwable );
      }
  
      /**
       * Determine if messages of priority "warn" will be logged.
       *
       * @return true if "warn" messages will be logged
       */
      public boolean isWarnEnabled()
      {
          return true;
      }
  
      /**
       * Log a error message.
       *
       * @param message the message
       */
      public void error( final String message )
      {
          error( message, null );
      }
  
      /**
       * Log a error message.
       *
       * @param message the message
       * @param throwable the throwable
       */
      public void error( final String message, final Throwable throwable )
      {
          append( "ERROR", message, throwable );
      }
  
      /**
       * Determine if messages of priority "error" will be logged.
       *
       * @return true if "error" messages will be logged
       */
      public boolean isErrorEnabled()
      {
          return true;
      }
  
      /**
       * Log a fatalError message.
       *
       * @param message the message
       */
      public void fatalError( final String message )
      {
          fatalError( message, null );
      }
  
      /**
       * Log a fatalError message.
       *
       * @param message the message
       * @param throwable the throwable
       */
      public void fatalError( final String message, final Throwable throwable )
      {
          append( "FATAL ERROR", message, throwable );
      }
  
      /**
       * Determine if messages of priority "fatalError" will be logged.
       *
       * @return true if "fatalError" messages will be logged
       */
      public boolean isFatalErrorEnabled()
      {
          return true;
      }
  
      /**
       * Create a new child logger.
       * The name of the child logger is [current-loggers-name].[passed-in-name]
       *
       * @param name the subname of this logger
       * @return the new logger
       */
      public Logger getChildLogger( final String name )
      {
          return this;
      }
  
      /**
       * Returns the contents of the buffer.
       *
       * @return the buffer contents
       *
       */
      public String toString()
      {
          return m_sb.toString();
      }
  
      private void append( final String level,
                           final String message,
                           final Throwable throwable )
      {
          synchronized( m_sb )
          {
              m_sb.append( level );
              m_sb.append( " - " );
              m_sb.append( message );
  
              if( null != throwable )
              {
                  final String stackTrace =
                      ExceptionUtil.printStackTrace( throwable );
                  m_sb.append( " : " );
                  m_sb.append( stackTrace );
              }
              m_sb.append( "\n" );
          }
      }
  }
  
  
  
  1.1                  avalon-excalibur/component/src/java/org/apache/avalon/excalibur/testcase/CascadingAssertionFailedError.java
  
  Index: CascadingAssertionFailedError.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.testcase;
  
  import junit.framework.AssertionFailedError;
  
  import org.apache.avalon.framework.CascadingThrowable;
  
  /**
   * This is an extention to the testing framework so that we can get detailed
   * messages from JUnit (The AssertionFailedError hides the underlying cause)
   *
   * @author <a href="mailto:giacomo@apache.org">Giacomo Pati</a>
   * @version $Id: CascadingAssertionFailedError.java,v 1.1 2003/03/07 19:34:31 bloritsch Exp $
   */
  public class CascadingAssertionFailedError
      extends AssertionFailedError
      implements CascadingThrowable
  {
      private final Throwable m_throwable;
  
      /**
       * Constructor with no message
       */
      public CascadingAssertionFailedError()
      {
          this( null, null );
      }
  
      /**
       * Constructor with a message
       */
      public CascadingAssertionFailedError( String message )
      {
          this( message, null );
      }
  
      /**
       * Constructor with a message and a parent exception
       */
      public CascadingAssertionFailedError( String message,
                                            Throwable parentThrowable )
      {
          super( message );
          m_throwable = parentThrowable;
      }
  
      /**
       * Return the parent exception
       */
      public final Throwable getCause()
      {
          return m_throwable;
      }
  }
  
  
  
  1.1                  avalon-excalibur/component/src/java/org/apache/avalon/excalibur/testcase/ComponentStateValidator.java
  
  Index: ComponentStateValidator.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.testcase;
  
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.activity.Suspendable;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.component.Recomposable;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Reconfigurable;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.Recontextualizable;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.logger.Loggable;
  import org.apache.avalon.framework.parameters.Parameterizable;
  import org.apache.avalon.framework.service.Serviceable;
  
  /**
   * This class provides basic facilities for enforcing Avalon's contracts
   * within your own code.
   *
   * Based on Avalon version from Sandbox.
   *
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   * @author <a href="mailto:mike@hihat.net">Michael McKibben</a>
   * @author <a href="mailto:leif@tanukisoftware.com">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2003/03/07 19:34:31 $
   */
  public final class ComponentStateValidator
  {
      private static final String WRITE_FAIL = "Value is already bound";
  
      // Interfaces
      private static final long LOG_ENABLED = 0x00000001;
      private static final long LOGGABLE = 0x00000002;
      private static final long CONTEXTUALIZABLE = 0x00000004;
      private static final long COMPOSABLE = 0x00000008;
      private static final long SERVICEABLE = 0x00000010;
      private static final long CONFIGURABLE = 0x00000020;
      private static final long PARAMETERIZABLE = 0x00000040;
      private static final long INITIALIZABLE = 0x00000080;
      private static final long STARTABLE = 0x00000100;
      private static final long SUSPENDABLE = 0x00001000;
      private static final long RECONTEXTUALIZABLE = 0x00002000;
      private static final long RECOMPOSABLE = 0x00004000;
      private static final long RECONFIGURABLE = 0x00008000;
      private static final long DISPOSABLE = 0x00100000;
  
      // Initialization Methods.
      private static final long ENABLE_LOGGING = 0x00000001;
      private static final long SET_LOGGER = 0x00000002;
      private static final long CONTEXTUALIZE = 0x00000004;
      private static final long SERVICE = 0x00000008;
      private static final long COMPOSE = 0x00000010;
      private static final long CONFIGURE = 0x00000020;
      private static final long PARAMETERIZE = 0x00000040;
      private static final long INITIALIZE = 0x00000080;
      private static final long START = 0x00000100;
      private static final long INIT_COMPLETE = 0x00000400;
  
      // Active Service Methods
      private static final long SUSPEND = 0x00001000;
      private static final long RECONTEXTUALIZE = 0x00002000;
      private static final long RECOMPOSE = 0x00004000;
      private static final long RECONFIGURE = 0x00008000;
      private static final long RESUME = 0x00010000;
  
      // Destruction Methods
      private static final long STOP = 0x00100000;
      private static final long DISPOSE = 0x00200000;
  
      // Masks
      private static final long INIT_MASK = ENABLE_LOGGING | SET_LOGGER |
          CONTEXTUALIZE | COMPOSE | SERVICE | CONFIGURE | PARAMETERIZE | INITIALIZE |
          START;
  
      private final long m_interfaces;
      private final long m_methods;
      private long m_state;
      private boolean m_active;
      private final Object m_object;
  
      /**
       * Create state validator from object (this can be used for more than just
       * components).
       */
      public ComponentStateValidator( final Object object )
      {
          m_object = object;
  
          long methods = 0;
          long interfaces = 0;
  
          if( object instanceof LogEnabled )
          {
              interfaces |= LOG_ENABLED;
              methods |= ENABLE_LOGGING;
          }
  
          if( object instanceof Loggable )
          {
              interfaces |= LOGGABLE;
              methods |= SET_LOGGER;
          }
  
          if( object instanceof Contextualizable )
          {
              interfaces |= CONTEXTUALIZABLE;
              methods |= CONTEXTUALIZE;
          }
  
          if( object instanceof Serviceable )
          {
              interfaces |= SERVICEABLE;
              methods |= SERVICE;
          }
  
          if( object instanceof Composable )
          {
              if( ( interfaces & SERVICEABLE ) > 0 )
              {
                  throw new IllegalStateException( "Cannot implement Composable and Serviceable together" );
              }
  
              interfaces |= COMPOSABLE;
              methods |= COMPOSE;
          }
  
          if( object instanceof Configurable )
          {
              interfaces |= CONFIGURABLE;
              methods |= CONFIGURE;
          }
  
          if( object instanceof Parameterizable )
          {
              interfaces |= PARAMETERIZABLE;
              methods |= PARAMETERIZE;
          }
  
          if( object instanceof Initializable )
          {
              interfaces |= INITIALIZABLE;
              methods |= INITIALIZE;
          }
  
          if( object instanceof Startable )
          {
              interfaces |= STARTABLE;
              methods |= START | STOP;
          }
  
          if( object instanceof Suspendable )
          {
              interfaces |= SUSPENDABLE;
              methods |= SUSPEND | RESUME;
          }
  
          if( object instanceof Recontextualizable )
          {
              interfaces |= RECONTEXTUALIZABLE;
              methods |= RECONTEXTUALIZE;
          }
  
          if( object instanceof Recomposable )
          {
              interfaces |= RECOMPOSABLE;
              methods |= RECOMPOSE;
          }
  
          if( object instanceof Reconfigurable )
          {
              interfaces |= RECONFIGURABLE;
              methods |= RECONFIGURE;
          }
  
          if( object instanceof Disposable )
          {
              interfaces |= DISPOSABLE;
              methods |= DISPOSE;
          }
  
          m_methods = methods;
          m_interfaces = interfaces;
  
          generalCheckInitComplete();
      }
  
      private String getInterfaceName( long interfaceId )
      {
          if( interfaceId == LOG_ENABLED )
          {
              return LogEnabled.class.getName();
          }
          else if( interfaceId == LOGGABLE )
          {
              return Loggable.class.getName();
          }
          else if( interfaceId == CONTEXTUALIZABLE )
          {
              return Contextualizable.class.getName();
          }
          else if( interfaceId == SERVICEABLE )
          {
              return Serviceable.class.getName();
          }
          else if( interfaceId == COMPOSABLE )
          {
              return Composable.class.getName();
          }
          else if( interfaceId == CONFIGURABLE )
          {
              return Configurable.class.getName();
          }
          else if( interfaceId == PARAMETERIZABLE )
          {
              return Parameterizable.class.getName();
          }
          else if( interfaceId == INITIALIZABLE )
          {
              return Initializable.class.getName();
          }
          else if( interfaceId == STARTABLE )
          {
              return Startable.class.getName();
          }
          else if( interfaceId == SUSPENDABLE )
          {
              return Suspendable.class.getName();
          }
          else if( interfaceId == RECONTEXTUALIZABLE )
          {
              return Recontextualizable.class.getName();
          }
          else if( interfaceId == RECOMPOSABLE )
          {
              return Recomposable.class.getName();
          }
          else if( interfaceId == RECONFIGURABLE )
          {
              return Reconfigurable.class.getName();
          }
          else if( interfaceId == DISPOSABLE )
          {
              return Disposable.class.getName();
          }
          else
          {
              throw new IllegalStateException( "Unknown Interface Id " + interfaceId );
          }
      }
  
      private String getMethodName( long methodId )
      {
          if( methodId == ENABLE_LOGGING )
          {
              return "enableLogging()";
          }
          else if( methodId == SET_LOGGER )
          {
              return "setLogger()";
          }
          else if( methodId == CONTEXTUALIZE )
          {
              return "contextualize()";
          }
          else if( methodId == SERVICE )
          {
              return "service()";
          }
          else if( methodId == COMPOSE )
          {
              return "compose()";
          }
          else if( methodId == CONFIGURE )
          {
              return "configure()";
          }
          else if( methodId == PARAMETERIZE )
          {
              return "parameterize()";
          }
          else if( methodId == INITIALIZE )
          {
              return "initialize()";
          }
          else if( methodId == START )
          {
              return "start()";
          }
          else if( methodId == SUSPEND )
          {
              return "suspend()";
          }
          else if( methodId == RECONTEXTUALIZE )
          {
              return "recontextualize()";
          }
          else if( methodId == RECOMPOSE )
          {
              return "recompose()";
          }
          else if( methodId == RECONFIGURE )
          {
              return "reconfigure()";
          }
          else if( methodId == RESUME )
          {
              return "resume()";
          }
          else if( methodId == STOP )
          {
              return "stop()";
          }
          else if( methodId == DISPOSE )
          {
              return "dispose()";
          }
          else
          {
              throw new IllegalStateException( "Unknown Method Id " + methodId );
          }
      }
  
      private String getLastMethod( long state )
      {
          for( int i = 31; i >= 0; i-- )
          {
              long methodId = 0x1 << i;
              if( ( state & methodId ) != 0 )
              {
                  return getMethodName( methodId );
              }
          }
          throw new IllegalStateException( "No last state method found for state " + state );
      }
  
      /**
       * Test to see if this was the last initialization method.
       */
      private void generalCheckInitComplete()
      {
          if( m_state == ( m_methods & INIT_MASK ) )
          {
              // All init methods called
              m_active = true;
          }
      }
  
      /**
       * Initialization methods must be called in order, must all be called, may
       *  not be called more than once, and may not be called once any of the
       *  Descruction methods have been called.
       */
      private void generalCheckInit( final String message, final long interfaceId, final long methodId )
      {
          if( ( m_interfaces & interfaceId ) == 0 )
          {
              // Interface not implemented
              if( message == null )
              {
                  throw new IllegalStateException( m_object.getClass().getName() +
                                                   " does not implement " + getInterfaceName( interfaceId ) + "." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
          else if( ( m_state & methodId ) > 0 )
          {
              // Method already called.
              if( message == null )
              {
                  throw new IllegalStateException( getMethodName( methodId ) + " already called." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
          else if( m_state > methodId )
          {
              // Method called after a descruction method was called.
              if( message == null )
              {
                  throw new IllegalStateException( getMethodName( methodId ) +
                                                   " can not be called after " + getLastMethod( m_state ) + "." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
          else if( ( m_state & ( methodId - 1 ) ) != ( m_methods & ( methodId - 1 ) ) )
          {
              // One or more of the methods that should have been called before
              //  this method was not.
              if( message == null )
              {
                  throw new IllegalStateException( getMethodName( methodId ) +
                                                   " called out of order. " + getLastMethod( m_methods & ( methodId - 1 ) ) +
                                                   " must be called first." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
  
          // Add this method to the state
          m_state |= methodId;
  
          // See if the initialization is complete.
          generalCheckInitComplete();
      }
  
      /**
       * Active Service methods may only be called after all of the
       *  Initialization methods have been called, any before any of the
       *  Descruction methods have been called.  While in the active state,
       *  the contracts of the methods allow the active state methods to be
       *  called any number of times, in any order.
       * The resume() method should do nothing if suspend() has not yet been
       *  called for example.
       */
      private void generalCheckActive( final String message, final long interfaceId, final long methodId )
      {
          if( ( m_interfaces & interfaceId ) == 0 )
          {
              // Interface not implemented
              if( message == null )
              {
                  throw new IllegalStateException( m_object.getClass().getName() +
                                                   " does not implement " + getInterfaceName( interfaceId ) + "." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
          else if( !m_active )
          {
              // Component not in the active state.
              if( m_state < INIT_COMPLETE )
              {
                  // Still expecting initialization methods.
                  if( message == null )
                  {
                      throw new IllegalStateException( getMethodName( methodId ) +
                                                       " called before component was made active. " +
                                                       getLastMethod( m_methods & ( INIT_COMPLETE - 1 ) ) +
                                                       " must be called first." );
                  }
                  else
                  {
                      throw new IllegalStateException( message );
                  }
              }
              else
              {
                  // One or more destruction methods have been called.
                  if( message == null )
                  {
                      throw new IllegalStateException( getMethodName( methodId ) +
                                                       " called after component was made inactive.  Cannot call after " +
                                                       getLastMethod( m_state ) + "." );
                  }
                  else
                  {
                      throw new IllegalStateException( message );
                  }
              }
          }
      }
  
      /**
       * Descruction Methods must be called in order.  They may be called before
       *  all of the Initialization methods have been called if there was an
       *  error.
       */
      private void generalCheckDest( final String message, final long interfaceId, final long methodId )
      {
          if( ( m_interfaces & interfaceId ) == 0 )
          {
              // Interface not implemented
              if( message == null )
              {
                  throw new IllegalStateException( m_object.getClass().getName() +
                                                   " does not implement " + getInterfaceName( interfaceId ) + "." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
          else if( m_state > methodId )
          {
              // Method called after a later descruction method was called.
              if( message == null )
              {
                  throw new IllegalStateException( getMethodName( methodId ) +
                                                   " can not be called after " + getLastMethod( m_state ) + "." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
  
          // Add this method to the state
          m_state |= methodId;
  
          // Deactivate
          m_active = false;
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the ENABLE_LOGGING state has already been set, if the component implements
       * LogEnabled, and if the state has progressed beyond the Logger stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkLogEnabled()
      {
          checkLogEnabled( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the ENABLE_LOGGING state has already been set, if the component implements
       * LogEnabled, and if the state has progressed beyond the Logger stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkLogEnabled( final String message )
      {
          generalCheckInit( message, LOG_ENABLED, ENABLE_LOGGING );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SET_LOGGER state has already been set, if the component implements
       * Loggable, and if the state has progressed beyond the Logger stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkLoggable()
      {
          checkLogEnabled( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SET_LOGGER state has already been set, if the component implements
       * Loggable, and if the state has progressed beyond the Logger stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkLoggable( final String message )
      {
          generalCheckInit( message, LOGGABLE, SET_LOGGER );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the CONTEXTUALIZED state has already been set, if the component implements
       * Contextualizable, and if the state has progressed beyond the Context stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkContextualized()
      {
          checkContextualized( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the CONTEXTUALIZED state has already been set, if the component implements
       * Contextualizable, and if the state has progressed beyond the Context stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkContextualized( final String message )
      {
          generalCheckInit( message, CONTEXTUALIZABLE, CONTEXTUALIZE );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SERVICE state has already been set, if the component implements
       * Composable, and if the state has progressed beyond the Configuration stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkServiced()
      {
          checkServiced( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SERVICE state has already been set, if the component implements
       * Composable, and if the state has progressed beyond the Configuration stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkServiced( final String message )
      {
          generalCheckInit( message, SERVICEABLE, SERVICE );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the COMPOSED state has already been set, if the component implements
       * Composable, and if the state has progressed beyond the Configuration stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkComposed()
      {
          checkComposed( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the COMPOSED state has already been set, if the component implements
       * Composable, and if the state has progressed beyond the Configuration stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkComposed( final String message )
      {
          generalCheckInit( message, COMPOSABLE, COMPOSE );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the CONFIGURED state has already been set, if the component implements
       * Configurable, and if the state has progressed beyond the Configuration stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkConfigured()
      {
          checkConfigured( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the CONFIGURED state has already been set, if the component implements
       * Configurable, and if the state has progressed beyond the Configuration stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkConfigured( final String message )
      {
          generalCheckInit( message, CONFIGURABLE, CONFIGURE );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the PARAMETERIZED state has already been set, if the component implements
       * Parameterizable, and if the state has progressed beyond the Parameters stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkParameterized()
      {
          checkParameterized( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the PARAMETERIZED state has already been set, if the component implements
       * Parameterizable, and if the state has progressed beyond the Parameters stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkParameterized( final String message )
      {
          generalCheckInit( message, PARAMETERIZABLE, PARAMETERIZE );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the INITIALIZED state has already been set, if the component implements
       * Initializable, and if the state has progressed beyond the <code>initialize</code> stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkInitialized()
      {
          checkInitialized( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the INITIALIZED state has already been set, if the component implements
       * Initializable, and if the state has progressed beyond the <code>initialize</code> stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkInitialized( final String message )
      {
          generalCheckInit( message, INITIALIZABLE, INITIALIZE );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the STARTED state has already been set, if the component implements
       * Startable, and if the state has progressed beyond the <code>start</code> stage.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkStarted()
      {
          checkStarted( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the STARTED state has already been set, if the component implements
       * Startable, and if the state has progressed beyond the <code>start</code> stage.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkStarted( final String message )
      {
          generalCheckInit( message, STARTABLE, START );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SUSPENDED state has already been set, if the component implements
       * Suspendable, and if the Component is active.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkSuspended()
      {
          checkSuspended( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SUSPENDED state has already been set, if the component implements
       * Suspendable, and if the Component is active.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkSuspended( final String message )
      {
          generalCheckActive( message, SUSPENDABLE, SUSPEND );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SUSPENDED state has not been set, if the component implements
       * Suspendable, and if the Component is active.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkResumed()
      {
          checkResumed( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the SUSPENDED state has not been set, if the component implements
       * Suspendable, and if the Component is active.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkResumed( final String message )
      {
          generalCheckActive( message, SUSPENDABLE, RESUME );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the STOPPED state has not been set, if the component implements
       * Startable, and if the Component is active.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkStopped()
      {
          checkStopped( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the STOPPED state has not been set, if the component implements
       * Startable, and if the Component is active.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkStopped( final String message )
      {
          generalCheckDest( message, STARTABLE, STOP );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the DISPOSED state has not been set, if the component implements
       * Disposable.
       *
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkDisposed()
      {
          checkDisposed( null );
      }
  
      /**
       * Throw an exception if the initialization is out of order.  It tests to see
       * if the DISPOSED state has not been set, if the component implements
       * Disposable.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkDisposed( final String message )
      {
          generalCheckDest( message, DISPOSABLE, DISPOSE );
      }
  
      /**
       * Checks to see if the state is active.
       *
       * @throws IllegalStateException if the component is not active
       */
      public void checkActive()
      {
          checkActive( null );
      }
  
      /**
       * Checks to see if the state is active.
       *
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the component is not active
       */
      public void checkActive( final String message )
      {
          if( isActive() )
          {
              return;
          }
  
          // Component not in the active state.
          if( m_state < INIT_COMPLETE )
          {
              // Still expecting initialization methods.
              if( message == null )
              {
                  throw new IllegalStateException( "Component not in the active state. " +
                                                   getLastMethod( m_methods & ( INIT_COMPLETE - 1 ) ) +
                                                   " was not called." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
          else
          {
              // One or more destruction methods have been called.
              if( message == null )
              {
                  throw new IllegalStateException( "Component not in the active state because " +
                                                   getLastMethod( m_state ) + " was called." );
              }
              else
              {
                  throw new IllegalStateException( message );
              }
          }
      }
  
      /**
       * Checks to see if the state is active, and returns true or false.
       *
       * @return <code>true</code> if active, <code>false</code> if not
       */
      public boolean isActive()
      {
          return m_active;
      }
  
      /**
       * Make sure object has not been assigned yet.
       *
       * @param object to test
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkNotAssigned( final Object object )
      {
          checkNotAssigned( object, WRITE_FAIL );
      }
  
      /**
       * Make sure object has not been assigned yet.
       *
       * @param object to test
       * @param message the message to include in the thrown exception
       * @throws IllegalStateException if the state is manage out of order
       */
      public void checkNotAssigned( final Object object, final String message )
      {
          if( null != object )
          {
              throw new IllegalStateException( message );
          }
      }
  }
  
  
  
  
  1.1                  avalon-excalibur/component/src/java/org/apache/avalon/excalibur/testcase/ExcaliburTestCase.java
  
  Index: ExcaliburTestCase.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.testcase;
  
  import java.io.InputStream;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  
  import junit.framework.AssertionFailedError;
  import junit.framework.TestCase;
  import junit.framework.TestResult;
  
  import org.apache.avalon.excalibur.component.DefaultRoleManager;
  import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
  import org.apache.avalon.excalibur.logger.DefaultLogKitManager;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.component.Component;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  import org.apache.avalon.framework.logger.LogKitLogger;
  import org.apache.log.Hierarchy;
  import org.apache.log.LogTarget;
  import org.apache.log.Logger;
  import org.apache.log.Priority;
  import org.apache.log.format.PatternFormatter;
  import org.apache.log.output.io.StreamTarget;
  
  /**
   * JUnit TestCase for Avalon Components.
   * <p>
   *   This class extends the JUnit TestCase class to setup an environment which
   *   makes it possible to easily test Avalon Components. The following methods
   *   and instance variables are exposed for convenience testing:
   * </p>
   * <dl>
   *   <dt>manager</dt>
   *   <dd>
   *     This instance variable contains an initialized ComponentLocator which
   *     can be used to lookup Components configured in the test configuration
   *     file. (see below)
   *   </dd>
   *   <dt>getLogger()</dt>
   *   <dd>
   *     This method returns the default logger for this test case
   *   </dd>
   * </dl>
   * <p>
   *   The following test case configuration can be used as a basis for new tests.
   *   Detailed are explanations of the configuration elements can be found after
   *   the example.  The example will log all logger output to the console and to
   *   a log file.
   * </p>
   * <pre>
   *   &lt;testcase&gt;
   *     &lt;annotation&gt;
   *       &lt;![CDATA[
   *         &lt;title&gt;{Name of test}&lt;/title&gt;
   *         &lt;para&gt;
   *           {Description of test}
   *           The configuration is specified in the file located in
   *           &lt;parameter&gt;avalon-excalibur/src/test/{path and name of conf file}.xtext&lt;/parameter&gt;.
   *         &lt;/para&gt;
   *       ]]&gt;
   *     &lt;/annotation&gt;
   *
   *     &lt;logkit log-level="INFO"&gt;
   *       &lt;factories&gt;
   *         &lt;factory type="stream" class="org.apache.avalon.excalibur.logger.factory.StreamTargetFactory"/&gt;
   *         &lt;factory type="file" class="org.apache.avalon.excalibur.logger.factory.FileTargetFactory"/&gt;
   *       &lt;/factories&gt;
   *
   *       &lt;targets&gt;
   *         &lt;stream id="console"&gt;
   *           &lt;stream&gt;System.out&lt;/stream&gt;
   *           &lt;format type="avalon"&gt;
   *             %7.7{priority} %23.23{time:yyyy-MM-dd' 'HH:mm:ss.SSS} [%30.30{category}] (%{context}): %{message}\n%{throwable}
   *           &lt;/format&gt;
   *         &lt;/stream&gt;
   *         &lt;file id="log-file"&gt;
   *           &lt;filename&gt;TEST-{full test class name}.log&lt;/filename&gt;
   *           &lt;format type="avalon"&gt;
   *             %7.7{priority} %23.23{time:yyyy-MM-dd' 'HH:mm:ss.SSS} [%30.30{category}] (%{context}): %{message}\n%{throwable}
   *           &lt;/format&gt;
   *         &lt;/file&gt;
   *       &lt;/targets&gt;
   *
   *       &lt;categories&gt;
   *         &lt;category name="test" log-level="INFO"&gt;
   *           &lt;log-target id-ref="console"/&gt;
   *           &lt;log-target id-ref="log-file"/&gt;
   *         &lt;/category&gt;
   *         &lt;category name="jdbc" log-level="INFO"&gt;
   *           &lt;log-target id-ref="console"/&gt;
   *           &lt;log-target id-ref="log-file"/&gt;
   *         &lt;/category&gt;
   *       &lt;/categories&gt;
   *     &lt;/logkit&gt;
   *
   *     &lt;context&gt;
   *       &lt;entry name="foo" value="bar"/&gt;
   *       &lt;entry name="baz" class="my.context.Class"/&gt;
   *     &lt;/context&gt;
   *
   *     &lt;roles&gt;
   *       &lt;role name="org.apache.avalon.excalibur.datasource.DataSourceComponentSelector"
   *             shorthand="datasources"
   *             default-class="org.apache.avalon.excalibur.component.ExcaliburComponentSelector"&gt;
   *          &lt;hint shorthand="jdbc" class="org.apache.avalon.excalibur.datasource.JdbcDataSource"/&gt;
   *       &lt;/role&gt;
   *     &lt;/roles&gt;
   *
   *     &lt;components&gt;
   *       &lt;datasources&gt;
   *         &lt;jdbc name="personell" logger="jdbc"&gt;
   *           &lt;pool-controller min="5" max="10"/&gt;
   *           &lt;jdbc name="personnel"/&gt;
   *           &lt;dburl&gt;jdbc:odbc:test&lt;/dburl&gt;
   *           &lt;user&gt;test&lt;/user&gt;
   *           &lt;password&gt;test&lt;/password&gt;
   *           &lt;driver&gt;sun.jdbc.odbc.JdbcOdbcDriver&lt;/driver&gt;
   *         &lt;/jdbc&gt;
   *       &lt;/datasources&gt;
   *     &lt;/components&gt;
   *   &lt;/testcase&gt;
   * </pre>
   * <p>
   * Element Explanation:
   * <dl>
   * <dt>testcase</dt>
   * <dd>Defines a test case configuration.  Must contain one each of the
   *  following elements: <code>annotation</code>, <code>logkit</code>,
   *  <code>context</code>, <code>roles</code>, and <code>components</code>
   *  </dd>.
   *
   * <dt>annotation</dt>
   * <dd>Defines a test annotation.  This element should define a block of
   *  XML enclosed within a CDATA element.  The XML should be made up of a
   *  <code>title</code> element, naming the test, and a <code>para</code>
   *  element which is used to describe the test.</dd>
   *
   * <dt>logkit</dt>
   * <dd>Configures the logger used by the test cases and the components used
   *  by the tests.  The <code>logkit</code> element takes two optional
   *  attributes:
   *      <dl>
   *      <dt>logger</dt><dd>Uses to name the logger which is used to bootstrap
   *       the LogKit logger.  (Defaults to <code>"lm"</code>)</dd>
   *      <dt>log-level</dt><dd>Because the logger used by the LogKit must be
   *       created before the Log Kit Manager is initialized, it must be fully
   *       configured before the <code>logkit</code> element is parsed.  This
   *       attribute allows the Log Kit's log priority to be set.  This log
   *       level will also become the default for the Role Manager, Component
   *       Manager, and all components if they do not have <code>category</code>
   *       elements declated in the <code>logkit</code> element.
   *       (Defaults to "INFO")</dd>
   *      </dl>
   *  The loggers used by test cases and components can be easily configured
   *  from within this file.  The default test configuration, shown above,
   *  includes a "test" category.  This category is used to configure the
   *  default logger for all test cases.  If it is set to "DEBUG", then all
   *  test debug logging will be enabled.  To enalble debug logging for a
   *  single test case, a child category must be defined for the
   *  "testCheckTotals" test case as follows:
   *  <pre>
   *       &lt;categories&gt;
   *         &lt;category name="test" log-level="INFO"&gt;
   *           &lt;log-target id-ref="console"/&gt;
   *           &lt;log-target id-ref="log-file"/&gt;
   *
   *           &lt;category name="testCheckTotals" log-level="DEBUG"&gt;
   *             &lt;log-target id-ref="console"/&gt;
   *             &lt;log-target id-ref="log-file"/&gt;
   *           &lt;/category&gt;
   *         &lt;/category&gt;
   *       &lt;/categories&gt;
   *  </pre>
   *  For general information on how to configure the LogKit Manager, please
   *  refer to the Log Kit documentation.
   * </dd>
   *
   * <dt>context</dt>
   * <dd>Allows context properties to be set in the context passed to any
   *  Contextualizable components.</dd>
   *
   * <dt>roles</dt>
   * <dd>Roles configuration for the Components configured in the
   *  <code>components</code> element.  The logger used by the RoleManager
   *  can be configured using a <code>logger</code> attribute, which defaults
   *  to "rm".  By default this logger will have the same log level and
   *  formatting as the LogKit logger.  It can be configured by adding a
   *  <code>category</code> within the <code>logkit</code> element.</dd>
   *
   * <dt>components</dt>
   * <dd>Used to configure any Components used by the test cases.  The logger
   *  used by the ComponentLocator can be configured using a <code>logger</code>
   *  attribute, which defaults to "cm".  By default this logger will have the
   *  same log level and formatting as the LogKit logger.  It can be configured
   *  by adding a <code>category</code> within the <code>logkit</code> element.
   *  </dd>
   *
   * </dl>
   *
   * @author <a href="mailto:giacomo@apache.org">Giacomo Pati</a>
   * @version $Id: ExcaliburTestCase.java,v 1.1 2003/03/07 19:34:31 bloritsch Exp $
   */
  public class ExcaliburTestCase
      extends TestCase
  {
      ///Format of default formatter
      private static final String FORMAT =
          "%7.7{priority} %23.23{time:yyyy-MM-dd' 'HH:mm:ss.SSS} [%30.30{category}] (%{context}): %{message}\n%{throwable}";
  
      //The default logger
      private Logger m_logger;
      private LogKitLogger m_logEnabledLogger;
      private ExcaliburComponentManager m_manager;
      private DefaultLogKitManager m_logKitManager;
      private static HashMap m_tests = new HashMap();
  
      protected ComponentManager manager;
  
      public ExcaliburTestCase( final String name )
      {
          super( name );
  
          ArrayList methodList = (ArrayList)ExcaliburTestCase.m_tests.get( getClass() );
  
          Method[] methods = getClass().getMethods();
  
          if( null == methodList )
          {
              methodList = new ArrayList( methods.length );
  
              for( int i = 0; i < methods.length; i++ )
              {
                  String methodName = methods[ i ].getName();
                  if( methodName.startsWith( "test" ) &&
                      ( Modifier.isPublic( methods[ i ].getModifiers() ) ) &&
                      ( methods[ i ].getReturnType().equals( Void.TYPE ) ) &&
                      ( methods[ i ].getParameterTypes().length == 0 ) )
                  {
                      methodList.add( methodName );
                  }
              }
  
              ExcaliburTestCase.m_tests.put( getClass(), methodList );
          }
      }
  
      /** Return the logger */
      protected Logger getLogger()
      {
          return m_logger;
      }
  
      /** Return the logger */
      protected LogKitLogger getLogEnabledLogger()
      {
          return m_logEnabledLogger;
      }
  
      /**
       * Initializes the ComponentLocator
       *
       * The configuration file is determined by the class name plus .xtest appended,
       * all '.' replaced by '/' and loaded as a resource via classpath
       */
      protected void prepare()
          throws Exception
      {
          final String resourceName = getClass().getName().replace( '.', '/' ) + ".xtest";
          URL resource = getClass().getClassLoader().getResource( resourceName );
  
          if( resource != null )
          {
              getLogger().debug( "Loading resource " + resourceName );
              prepare( resource.openStream() );
          }
          else
          {
              getLogger().debug( "Resource not found " + resourceName );
          }
      }
  
      /**
       * Initializes the ComponentLocator
       *
       * @param testconf The configuration file is passed as a <code>InputStream</code>
       *
       * A common way to supply a InputStream is to overwrite the initialize() method
       * in the sub class, do there whatever is needed to get the right InputStream object
       * supplying a conformant xtest configuartion and pass it to this initialize method.
       * the mentioned initialize method is also the place to set a different logging priority
       * to the member variable m_logPriority.
       */
      protected final void prepare( final InputStream testconf )
          throws Exception
      {
          getLogger().debug( "ExcaliburTestCase.initialize" );
  
          final DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
          final Configuration conf = builder.build( testconf );
  
          String annotation = conf.getChild( "annotation" ).getValue( null );
  
          if( ( null != annotation ) && !( "".equals( annotation ) ) )
          {
              m_logger.info( annotation );
          }
  
          Context context = setupContext( conf.getChild( "context" ) );
  
          setupManagers( conf.getChild( "components" ),
                         conf.getChild( "roles" ),
                         conf.getChild( "logkit" ),
                         context );
          manager = m_manager;
  
          setCurrentLogger( "prepare" );
      }
  
      /**
       * Disposes the <code>ComponentLocator</code>
       */
      final private void done()
      {
          if( null != m_manager )
          {
              m_manager.dispose();
          }
  
          m_manager = null;
      }
  
      /**
       * Exctract the base class name of a class.
       */
      private String getBaseClassName( Class clazz )
      {
          String name = clazz.getName();
          int pos = name.lastIndexOf( '.' );
          if( pos >= 0 )
          {
              name = name.substring( pos + 1 );
          }
          return name;
      }
  
      /**
       * Override <code>run</code> so that we can have code that is run once.
       */
      final public void run( TestResult result )
      {
          ArrayList methodList = (ArrayList)ExcaliburTestCase.m_tests.get( getClass() );
  
          if( null == methodList || methodList.isEmpty() )
          {
              return; // The test was already run!  NOTE: this is a hack.
          }
  
          // Set the logger for the initialization phase.
          setCurrentLogger( getBaseClassName( getClass() ) );
  
          try
          {
              if( this instanceof Initializable )
              {
                  ( (Initializable)this ).initialize();
              }
  
              prepare();
  
              Iterator tests = methodList.iterator();
  
              while( tests.hasNext() )
              {
                  String methodName = (String)tests.next();
                  setName( methodName );
                  setCurrentLogger( methodName );
  
                  if( getLogger().isDebugEnabled() )
                  {
                      getLogger().debug( "" );
                      getLogger().debug( "========================================" );
                      getLogger().debug( "  begin test: " + methodName );
                      getLogger().debug( "========================================" );
                  }
  
                  super.run( result );
  
                  if( getLogger().isDebugEnabled() )
                  {
                      getLogger().debug( "========================================" );
                      getLogger().debug( "  end test: " + methodName );
                      getLogger().debug( "========================================" );
                      getLogger().debug( "" );
                  }
              }
  
          }
          catch( Exception e )
          {
              System.out.println( e );
              e.printStackTrace();
              result.addError( this, e );
          }
          finally
          {
              done();
  
              if( this instanceof Disposable )
              {
                  try
                  {
                      ( (Disposable)this ).dispose();
                  }
                  catch( Exception e )
                  {
                      result.addFailure( this, new AssertionFailedError( "Disposal Error" ) );
                  }
              }
          }
  
          methodList.clear();
          ExcaliburTestCase.m_tests.put( getClass(), methodList );
      }
  
      /**
       * Sets the logger which will be returned by getLogger and getLogEnabledLogger
       */
      final private void setCurrentLogger( String name )
      {
          org.apache.log.Logger logger;
          if( m_logKitManager == null )
          {
              // Logger for the portion of the configuration has been loaded.
              logger = Hierarchy.getDefaultHierarchy().getLoggerFor( name );
              logger.setPriority( Priority.INFO );
  
              PatternFormatter formatter = new PatternFormatter( FORMAT );
              StreamTarget target = new StreamTarget( System.out, formatter );
              logger.setLogTargets( new LogTarget[]{target} );
          }
          else
          {
              logger = m_logKitManager.getLogger( "test." + name );
          }
  
          /*
          //FIXME(GP): This method should setup a LogConfigurator and LogManager
          //           according to the configuration spec. not yet completed/implemented
          //           It will return a default logger for now.
          final org.apache.log.Logger logger = Hierarchy.getDefaultHierarchy().getLoggerFor( name );
          logger.setPriority( m_logPriority );
  
          final PatternFormatter formatter = new PatternFormatter( FORMAT );
          final StreamTarget target = new StreamTarget( System.out, formatter );
          logger.setLogTargets( new LogTarget[] { target } );
          */
  
          m_logger = logger;
          m_logEnabledLogger = new LogKitLogger( m_logger );
      }
  
      /**
       * set up a context according to the xtest configuration specifications context
       * element.
       *
       * A method addContext(DefaultContext context) is called here to enable subclasses
       * to put additional objects into the context programmatically.
       */
      final private Context setupContext( final Configuration conf )
          throws Exception
      {
          //FIXME(GP): This method should setup the Context object according to the
          //           configuration spec. not yet completed
          final DefaultContext context = new DefaultContext();
          final Configuration[] confs = conf.getChildren( "entry" );
          for( int i = 0; i < confs.length; i++ )
          {
              final String key = confs[ i ].getAttribute( "name" );
              final String value = confs[ i ].getAttribute( "value", null );
              if( value == null )
              {
                  String clazz = confs[ i ].getAttribute( "class" );
                  Object obj = getClass().getClassLoader().loadClass( clazz ).newInstance();
                  context.put( key, obj );
                  if( getLogger().isInfoEnabled() )
                      getLogger().info( "ExcaliburTestCase: added an instance of class " + clazz + " to context entry " + key );
              }
              else
              {
                  context.put( key, value );
                  if( getLogger().isInfoEnabled() )
                      getLogger().info( "ExcaliburTestCase: added value \"" + value + "\" to context entry " + key );
              }
          }
          addContext( context );
          return ( context );
      }
  
      /**
       * This method may be overwritten by subclasses to put additional objects
       * into the context programmatically.
       */
      protected void addContext( DefaultContext context )
      {
      }
  
      final private void setupManagers( final Configuration confCM,
                                        final Configuration confRM,
                                        final Configuration confLM,
                                        final Context context )
          throws Exception
      {
          // Setup the log manager.  Get the logger name and log level from attributes
          //  in the <logkit> node
          String lmLoggerName = confLM.getAttribute( "logger", "lm" );
          String lmLogLevel = confLM.getAttribute( "log-level", "INFO" );
          Priority lmPriority = Priority.getPriorityForName( lmLogLevel );
          DefaultLogKitManager logKitManager = new DefaultLogKitManager();
          Logger lmLogger = Hierarchy.getDefaultHierarchy().getLoggerFor( lmLoggerName );
          lmLogger.setPriority( lmPriority );
          logKitManager.enableLogging( new LogKitLogger( lmLogger ) );
          logKitManager.contextualize( context );
          logKitManager.configure( confLM );
          Hierarchy h = logKitManager.getHierarchy();
          h.setDefaultPriority( lmPriority );
          m_logKitManager = logKitManager;
  
          // Setup the RoleManager
          String rmLoggerName = confRM.getAttribute( "logger", "rm" );
          DefaultRoleManager roleManager = new DefaultRoleManager();
          roleManager.setLogger( logKitManager.getLogger( rmLoggerName ) );
          roleManager.configure( confRM );
  
          // Set up the ComponentLocator
          String cmLoggerName = confCM.getAttribute( "logger", "cm" );
          ExcaliburComponentManager manager = new ExcaliburComponentManager();
          manager.setLogger( logKitManager.getLogger( cmLoggerName ) );
          manager.setLogKitManager( logKitManager );
          manager.contextualize( context );
          manager.setRoleManager( roleManager );
          manager.configure( confCM );
          manager.initialize();
          m_manager = manager;
      }
  
      protected final Object lookup( final String key )
          throws ComponentException
      {
          return manager.lookup( key );
      }
  
      protected final void release( final Component object )
      {
          manager.release( object );
      }
  }
  
  
  
  1.1                  avalon-excalibur/component/src/java/org/apache/avalon/excalibur/testcase/FullLifecycleComponent.java
  
  Index: FullLifecycleComponent.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.testcase;
  
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.activity.Suspendable;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.parameters.ParameterException;
  import org.apache.avalon.framework.parameters.Parameterizable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.Serviceable;
  import org.apache.avalon.framework.thread.ThreadSafe;
  
  /**
   * This test class is used to test the AbstractComponent facilities for you.
   *
   * @author <a href="bloritsch@apache.org">Berin Loritsch</a>
   * @version CVS $Revision: 1.1 $ $Date: 2003/03/07 19:34:31 $
   */
  public final class FullLifecycleComponent
      implements LogEnabled, Contextualizable, Parameterizable, Configurable,
      Serviceable, Initializable, Startable, Suspendable, Disposable,
      ThreadSafe
  {
      private ComponentStateValidator m_validator = new ComponentStateValidator( this );
      private Logger m_logger;
      private Context m_context;
      private Parameters m_parameters;
      private Configuration m_configuration;
      private ServiceManager m_manager;
  
      public void enableLogging( Logger logger )
      {
          m_validator.checkNotAssigned( m_logger );
          m_validator.checkLogEnabled();
  
          m_logger = logger;
      }
  
      public void contextualize( Context context )
          throws ContextException
      {
          m_validator.checkNotAssigned( m_context );
          m_validator.checkContextualized();
  
          m_context = context;
      }
  
      public void parameterize( Parameters params )
          throws ParameterException
      {
          m_validator.checkNotAssigned( m_parameters );
          m_validator.checkParameterized();
  
          m_parameters = params;
      }
  
      public void configure( Configuration config )
          throws ConfigurationException
      {
          m_validator.checkNotAssigned( m_configuration );
          m_validator.checkConfigured();
  
          m_configuration = config;
      }
  
      public void service( ServiceManager manager )
          throws ServiceException
      {
          m_validator.checkNotAssigned( m_manager );
          m_validator.checkComposed();
          m_manager = manager;
      }
  
      public void initialize()
          throws Exception
      {
          m_validator.checkInitialized();
      }
  
      public void start()
          throws Exception
      {
          m_validator.checkStarted();
      }
  
      public void suspend()
      {
          m_validator.checkSuspended();
      }
  
      public void resume()
      {
          m_validator.checkResumed();
      }
  
      public void stop()
          throws Exception
      {
          m_validator.checkStopped();
      }
  
      public void dispose()
      {
          m_validator.checkDisposed();
  
          m_logger = null;
          m_context = null;
          m_parameters = null;
          m_configuration = null;
          m_manager = null;
      }
  }
  
  
  
  1.1                  avalon-excalibur/component/src/java/org/apache/avalon/excalibur/testcase/LatchedThreadGroup.java
  
  Index: LatchedThreadGroup.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.testcase;
  
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  
  /**
   * This class is useful for writing MultiThreaded test cases where you need to perform
   *  multithreaded load testing on a component.
   * <p>
   * An instance of will create a block of threads of the specified size.  Each thread will be
   *  assigned to run a specified Runnable instance.  The threads will then all wait at a latch
   *  until the go method is called.  The go method will not return until all of the
   *  Runnables have completed.
   *
   * @author <a href="mailto:leif@tanukisoftware.com">Leif Mortenson</a>
   * @version $Id: LatchedThreadGroup.java,v 1.1 2003/03/07 19:34:31 bloritsch Exp $
   */
  public class LatchedThreadGroup
      extends AbstractLogEnabled
  {
      private Thread[] m_threads;
      private Object m_semaphore = new Object();
      private int m_startedCount;
      private boolean m_latched;
      private int m_completedCount;
      private Throwable m_exception;
  
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a LatchedThreadGroup with a thread for each Runnable in the runnables array.
       */
      public LatchedThreadGroup( Runnable[] runnables )
      {
          int threadCount = runnables.length;
          m_threads = new Thread[ threadCount ];
          for( int i = 0; i < threadCount; i++ )
          {
              m_threads[ i ] = new Runner( runnables[ i ], "Latched_Thread_" + i );
          }
      }
  
      /**
       * Creates a LatchedThreadGroup with threadCount threads each running runnable.
       */
      public LatchedThreadGroup( Runnable runnable, int threadCount )
      {
          m_threads = new Thread[ threadCount ];
          for( int i = 0; i < threadCount; i++ )
          {
              m_threads[ i ] = new Runner( runnable, "Latched_Thread_" + i );
          }
      }
  
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      protected void resetMemory()
      {
          System.gc();
          System.gc();
  
          // Let the system settle down.
          try
          {
              Thread.sleep( 50 );
          }
          catch( InterruptedException e )
          {
          }
          Runtime runtime = Runtime.getRuntime();
          getLogger().debug( "Memory: " + ( runtime.totalMemory() - runtime.freeMemory() ) );
      }
  
      /**
       * Causes all of the Runnables to start at the same instance.  This method will return
       *  once all of the Runnables have completed.
       *
       * @return time, in milliseconds, that it took for all of the Runnables to complete.
       */
      public long go()
          throws Exception
      {
          // Start each of the threads.  They will block until the latch is released.  This is
          //  necessary because it takes some time for the threads to each allocate their required
          //  system resources and actually be ready to run.
          int threadCount = m_threads.length;
          for( int i = 0; i < threadCount; i++ )
          {
              m_threads[ i ].start();
          }
  
          // Wait for all of the threads to start before starting to time the test
          synchronized( m_semaphore )
          {
              while( m_startedCount < threadCount )
              {
                  m_semaphore.wait();
              }
  
              // Start clean
              resetMemory();
  
              // Release the threads.
              m_latched = true;
              getLogger().debug( "Main thread released the test thread latch." );
              m_semaphore.notifyAll();
          }
          // Start timing
          long startTime = System.currentTimeMillis();
  
          // Wait for all of the threads to complete
          synchronized( m_semaphore )
          {
              getLogger().debug( "Waiting for test threads to all complete." );
              while( m_completedCount < threadCount )
              {
                  try
                  {
                      m_semaphore.wait();
                  }
                  catch( InterruptedException e )
                  {
                  }
              }
          }
          final long duration = System.currentTimeMillis() - startTime;
          getLogger().debug( "All test threads completed." );
  
          if( m_exception != null )
          {
              throw new CascadingAssertionFailedError( "Exception in test thread.", m_exception );
          }
          return duration;
      }
  
      /**
       * Inner access method to getLogger() to work around a bug in the Javac compiler
       *  when getLogger() is called from the method of an inner class.  Jikes seems to
       *  handle it Ok. :-/
       */
      private Logger getInnerLogger()
      {
          return getLogger();
      }
  
      /*---------------------------------------------------------------
       * Inner Classes
       *-------------------------------------------------------------*/
      private class Runner extends Thread
      {
          private Runnable m_runnable;
  
          protected Runner( Runnable runnable, String name )
          {
              super( name );
              m_runnable = runnable;
          }
  
          public void run()
          {
              try
              {
                  // Need all threads to wait until all the others are ready.
                  synchronized( m_semaphore )
                  {
                      m_startedCount++;
                      getInnerLogger().debug( "Started " + m_startedCount + " test threads." );
                      if( m_startedCount >= m_threads.length )
                      {
                          m_semaphore.notifyAll();
                      }
                      while( !m_latched )
                      {
                          try
                          {
                              m_semaphore.wait();
                          }
                          catch( InterruptedException e )
                          {
                          }
                      }
                  }
  
                  // Run the runnable
                  try
                  {
                      m_runnable.run();
                  }
                  catch( Throwable t )
                  {
                      synchronized( m_semaphore )
                      {
                          getInnerLogger().error( "Error in " + Thread.currentThread().getName(), t );
                          if( m_exception != null )
                          {
                              m_exception = t;
                          }
                      }
                  }
              }
              finally
              {
                  // Say that we are done
                  synchronized( m_semaphore )
                  {
                      m_completedCount++;
                      getInnerLogger().debug( m_completedCount + " test threads completed." );
                      m_semaphore.notifyAll();
                  }
              }
          }
      }
  }
  
  
  

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


Mime
View raw message