You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by le...@apache.org on 2002/03/03 16:59:45 UTC

cvs commit: jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui AbstractInternalFrame.java DesktopPane.java LineChart.java MenuBar.java ProfileSampleFrame.java ProfilerFrame.java

leif        02/03/03 07:59:44

  Added:       src/scratchpad/org/apache/avalon/excalibur/altprofile
                        AbstractProfilePoint.java CounterProfilePoint.java
                        Profilable.java ProfilePoint.java
                        ValueProfilePoint.java
               src/scratchpad/org/apache/avalon/excalibur/altprofile/component
                        ProfilerComponentHandler.java
                        ProfilerComponentManager.java
                        ProfilerComponentSelector.java
                        ProfilerDefaultComponentFactory.java
               src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler
                        AbstractProfileSample.java
                        AbstractValueProfileSample.java
                        AverageValueProfileSample.java
                        CounterProfilePointListener.java
                        CounterProfileSample.java
                        DefaultProfilerManager.java
                        MaximumValueProfileSample.java
                        MinimumValueProfileSample.java
                        NoSuchProfilableException.java
                        NoSuchProfilePointException.java
                        NoSuchProfileSampleException.java
                        ProfilableDescriptor.java ProfilableProxy.java
                        ProfilePointDescriptor.java ProfilePointProxy.java
                        ProfileSample.java ProfileSampleDescriptor.java
                        ProfileSampleFactory.java
                        ProfileSampleListener.java
                        ProfileSampleSnapshot.java ProfilerManageable.java
                        ProfilerManager.java ValueProfilePointListener.java
               src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui
                        AbstractInternalFrame.java DesktopPane.java
                        LineChart.java MenuBar.java ProfileSampleFrame.java
                        ProfilerFrame.java
  Log:
  New Profiler Implementation
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/AbstractProfilePoint.java
  
  Index: AbstractProfilePoint.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.altprofile;
  
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilePointProxy;
  
  /**
   * The ProfilPoint interface must by implemented by any object wishing to act
   *  as a profile point used by the profiler.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public abstract class AbstractProfilePoint
      implements ProfilePoint
  {
      /** The name of the ProfilePoint. */
      private String m_name;
      
      /** Proxy object used to communicate with the ProfilerManager. */
      protected ProfilePointProxy m_proxy;
      
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new AbstractProfilePoint.
  	 *
  	 * @param name The name of the ProfilePoint.  The value should be a string
  	 *             which does not contain spaces or periods.
  	 */
      protected AbstractProfilePoint( String name )
      {
          m_name = name;
      }
      
      /*---------------------------------------------------------------
  	 * ProfilePoint Methods
  	 *-------------------------------------------------------------*/
  	/**
  	 * Gets the name for the ProfilePoint.  When a Profilable publishes more
  	 *  than one ProfilePoint, this name makes it possible to identify each
  	 *  ProfilePoint.  The value should be a string which does not contain
  	 *  spaces or periods.
  	 *
  	 * @return The name of the ProfilePoint.
  	 */
  	public String getProfilePointName()
  	{
          return m_name;
      }
      
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      /**
  	 * When the ProfilerManager is present, a ProfilePointProxy will be set
  	 *  to enable the ProfilePoint to communicate with the ProfileManager.
  	 *  Once the ProfilePointProxy is set, it should never be changed or set
  	 *  back to null.
  	 *
  	 * @param proxy Proxy object used to communicate with the ProfilerManager.
  	 */
      public void setProfilePointProxy( ProfilePointProxy proxy )
      {
  		if ( m_proxy != null )
  		{
  			throw new IllegalStateException(
  				"Once a ProfilePointProxy has been set, it can not be changed." );
  		}
          m_proxy = proxy;
      }
      
      /**
  	 * Used by classes being profiled so that they can avoid unnecessary
  	 *  code when the data from a ProfilePoint is not being used.
  	 *
  	 * @returns True if a ProfilePointProxy has been set and is active.
  	 */
  	public boolean isActive()
  	{
  		return ( m_proxy != null ) && ( m_proxy.isActive() );
  	}
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/CounterProfilePoint.java
  
  Index: CounterProfilePoint.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.altprofile;
  
  /**
   * CounterProfilePoints can be used to profile the number of times that
   *  something happens.  They are perfect for profiling things like the number
   *  of times a class instance is created or destroyed.  Or the number of
   *  times that a method is accessed.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class CounterProfilePoint
      extends AbstractProfilePoint
  {
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new CounterProfilePoint.
  	 *
  	 * @param name The name of the ProfilePoint.  The value should be a string
  	 *             which does not contain spaces or periods.
  	 */
      public CounterProfilePoint( String name )
      {
          super( name );
      }
      
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      /*
  	 * Increments the ProfilePoint.  This method is optimized to be extremely
  	 *  light weight when a ProfilerManager is not present and there are no
  	 *  registered CounterProfilePointListeners.
  	 */
      public void increment()
      {
          if ( m_proxy != null )
          {
              m_proxy.increment();
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/Profilable.java
  
  Index: Profilable.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.altprofile;
  
  /**
   * The Profilable interface is to mark objects that can be sampled by a
   *  Profiler.  The getProfilePoints method may or may not be called depending
   *  on whether or not the ComponentManager used to create the Component
   *  supports profiling.  In most cases, a profilable object should always
   *  create its internal ProfilePoints and make use of them as if profiling
   *  is going on.  The ProfilePoints are optimized so as not to reduce
   *  performance when they are not being used.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface Profilable
  {
      /**
       * Empty ProfilePoint array for use in hierarchical Profilable systems.
       */
      ProfilePoint[] EMPTY_PROFILE_POINT_ARRAY = new ProfilePoint[] {};
      
      /**
       * Empty Profilable array for use in hierarchical Profilable systems.
       */
      Profilable[] EMPTY_PROFILABLE_ARRAY = new Profilable[] {};
      
      /**
       * Sets the name for the Profilable.  The Profilable Name is used to
       *  uniquely identify the Profilable during the configuration of the
       *  Profiler and to gain access to a ProfilableDescriptor through a
       *  ProfilerManager.  The value should be a string which does not
       *  contain spaces or periods.
       * <p>
       * This value may be set by a parent Profilable, or by the ProfilerManager
       *  using the value of the 'profilable' attribute in the configuration
       *  of the component.
       *
       * @param name The name used to identify a Profilable.
       */
      void setProfilableName( String name );
      
      /**
       * Gets the name of the Profilable.  The Profilable Name is used to
       *  uniquely identify the Profilable during the configuration of the
       *  Profiler and to gain access to a ProfilableDescriptor through a
       *  ProfilerManager.  The value should be a string which does not 
       *  contain spaces or periods.
       *
       * @return The name used to identify a Profilable.
       */
      String getProfilableName();
  
      /**
       * Obtain a reference to all the ProfilePoints that the Profilable
       * object wishes to expose.  All sampling is done directly through
       * the ProfilePoints as opposed to the Profilable interface.
       *
       * @return An array of the ProfilePoints available for profiling.
       *         Should never be null.  If there are no ProfilePoints, then
       *         EMPTY_PROFILE_POINT_ARRAY can be returned.  This should
       *         never be the case though unless there are child Profilables
       *         with ProfilePoints.
       */
      ProfilePoint[] getProfilePoints();
  
      /**
       * Any Object which implements Profilable can also make use of other
       *  Profilable child objects.  This method is used to tell the Profiler
       *  about them.
       *
       * @return An array of child Profilables.  This method should never
       *         return null.  If there are no child Profilables, then
       *         EMPTY_PROFILABLE_ARRAY can be returned.
       */
      Profilable[] getChildProfilables();
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/ProfilePoint.java
  
  Index: ProfilePoint.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.altprofile;
  
  /**
   * The ProfilPoint interface must by implemented by any object wishing to act
   *  as a profile point used by the profiler.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface ProfilePoint
  {
      /**
       * Gets the name for the ProfilePoint.  When a Profilable publishes more
       *  than one ProfilePoint, this name makes it possible to identify each
       *  ProfilePoint.  The value should be a string which does not contain
       *  spaces or periods.
       *
       * @return The name of the ProfilePoint.
       */
      String getProfilePointName();
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/ValueProfilePoint.java
  
  Index: ValueProfilePoint.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.altprofile;
  
  /**
   * Objects implementing Profilable can create ProfilePoints with integer
   *  values using a ValueProfilePoint.  ValueProfilePoints are perfect for
   *  profiling things like system memory, or the size of a pool or cache.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ValueProfilePoint
      extends AbstractProfilePoint
  {
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new ValueProfilePoint.
  	 *
  	 * @param name The name of the ProfilePoint.  The value should be a string
  	 *             which does not contain spaces or periods.
  	 */
      public ValueProfilePoint( String name )
      {
          super( name );
      }
      
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      /**
  	 * Sets the current value of the ProfilePoint.  This method is optimized
  	 *  to be extremely light weight when a ProfilerManager is not present
  	 *  and there are no registered ValueProfilePointListeners.
  	 *
  	 * @param value The new value for the ProfilePoint.
  	 */
      public void setValue( int value )
      {
          if ( m_proxy != null )
          {
              m_proxy.setValue( value );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/component/ProfilerComponentHandler.java
  
  Index: ProfilerComponentHandler.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.altprofile.component;
  
  import org.apache.avalon.excalibur.altprofile.Profilable;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.component.ComponentHandler;
  import org.apache.avalon.excalibur.component.DefaultComponentFactory;
  import org.apache.avalon.excalibur.component.DefaultComponentHandler;
  import org.apache.avalon.excalibur.component.PoolableComponentHandler;
  import org.apache.avalon.excalibur.component.RoleManager;
  import org.apache.avalon.excalibur.component.ThreadSafeComponentHandler;
  import org.apache.avalon.excalibur.logger.LogKitManager;
  import org.apache.avalon.excalibur.pool.Poolable;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.thread.SingleThreaded;
  import org.apache.avalon.framework.thread.ThreadSafe;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public abstract class ProfilerComponentHandler
      extends ComponentHandler
  {
      /*---------------------------------------------------------------
       * Static Methods
       *-------------------------------------------------------------*/
      /**
       *
       *
       * @param componentClass Class of the component for which the handle is
       *                       being requested.
       * @param configuration The configuration for this component.
       * @param componentManager The ComponentManager which will be managing
       *                         the Component.
       * @param context The current context object.
       * @param roleManager The current RoleManager.
       * @param logkitManager The current LogKitManager.
       * @param profilerManager The current ProfilerManager.
       *
       * @throws Exception If there were any problems obtaining a ComponentHandler
       */
      public static ComponentHandler getComponentHandler(
                              final Class componentClass,
                              final Configuration config,
                              final ComponentManager componentManager,
                              final Context context,
                              final RoleManager roleManager,
                              final LogKitManager logkitManager,
                              final ProfilerManager profilerManager )
          throws Exception
      {
          int numInterfaces = 0;
  
          if ( SingleThreaded.class.isAssignableFrom( componentClass ) )
          {
              numInterfaces++;
          }
  
          if ( ThreadSafe.class.isAssignableFrom( componentClass ) )
          {
              numInterfaces++;
          }
  
          if ( Poolable.class.isAssignableFrom( componentClass ) )
          {
              numInterfaces++;
          }
  
          if ( numInterfaces > 1 )
          {
              throw new Exception("[CONFLICT] lifestyle interfaces: " + componentClass.getName());
          }
          
          // Create the factory to use to create the instances of the Component.
          DefaultComponentFactory factory =
              new ProfilerDefaultComponentFactory( componentClass,
                                                   config,
                                                   componentManager,
                                                   context,
                                                   roleManager,
                                                   logkitManager,
                                                   profilerManager );
  
          if ( Poolable.class.isAssignableFrom( componentClass ) )
          {
              return new PoolableComponentHandler( factory, config );
          }
          else if ( ThreadSafe.class.isAssignableFrom( componentClass ) )
          {
              return new ThreadSafeComponentHandler( factory, config );
          }
          else // This is a SingleThreaded component
          {
              return new DefaultComponentHandler( factory, config );
          }
      }
      
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new ProfilerComponentHandler.
       */
      public ProfilerComponentHandler() {}
      
      /*---------------------------------------------------------------
       * ComponentHandler Methods
       *-------------------------------------------------------------*/
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/component/ProfilerComponentManager.java
  
  Index: ProfilerComponentManager.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.altprofile.component;
  
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.component.ComponentHandler;
  import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
  import org.apache.avalon.excalibur.component.RoleManager;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.excalibur.logger.LogKitManager;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfilerComponentManager
      extends ExcaliburComponentManager
  {
      private ProfilerManager m_profilerManager;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new ProfilerComponentManager.
       */
      public ProfilerComponentManager()
      {
          super();
      }
      
      /**
       * Creates a new ProfilerComponentManager which will use the specified
       *  class loader to load all of its components.
       */
      public ProfilerComponentManager( ClassLoader classLoader )
      {
          super( classLoader );
      }
      
      /*---------------------------------------------------------------
       * ExcaliburComponentManager Methods
       *-------------------------------------------------------------*/
      /**
       * Obtain a new ComponentHandler for the specified component.  This method
       *  allows classes which extend the ExcaliburComponentManager to use their
       *  own ComponentHandlers.
       *
       * @param componentClass Class of the component for which the handle is
       *                       being requested.
       * @param configuration The configuration for this component.
       * @param context The current context object.
       * @param roleManager The current RoleManager.
       * @param logkitManager The current LogKitManager.
       *
       * @throws Exception If there were any problems obtaining a ComponentHandler
       */
      protected ComponentHandler getComponentHandler( final Class componentClass,
                                                      final Configuration configuration,
                                                      final Context context,
                                                      final RoleManager roleManager,
                                                      final LogKitManager logkitManager )
          throws Exception
      {
          if ( m_profilerManager == null )
          {
              throw new IllegalStateException( "The ProfilerManager was not yet set." );
          }
                                                      
          return ProfilerComponentHandler.getComponentHandler( componentClass,
                                                               configuration,
                                                               this,
                                                               context,
                                                               roleManager,
                                                               logkitManager,
                                                               m_profilerManager );
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      public void setProfilerManager( ProfilerManager profilerManager )
      {
          m_profilerManager = profilerManager;
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/component/ProfilerComponentSelector.java
  
  Index: ProfilerComponentSelector.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.altprofile.component;
  
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManageable;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.component.ComponentHandler;
  import org.apache.avalon.excalibur.component.ExcaliburComponentSelector;
  import org.apache.avalon.excalibur.component.RoleManager;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.excalibur.logger.LogKitManager;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfilerComponentSelector
      extends ExcaliburComponentSelector
      implements ProfilerManageable
  {
      private ProfilerManager m_profilerManager;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new ProfilerComponentSelector.
       */
      public ProfilerComponentSelector()
      {
          super();
      }
      
      /**
       * Creates a new ProfilerComponentSelector which will use the specified
       *  class loader to load all of its components.
       */
      public ProfilerComponentSelector( ClassLoader classLoader )
      {
          super( classLoader );
      }
      
      /*---------------------------------------------------------------
       * ExcaliburComponentSelector Methods
       *-------------------------------------------------------------*/
      /**
       * Obtain a new ComponentHandler for the specified component.  This method
       *  allows classes which extend the ExcaliburComponentSelector to use their
       *  own ComponentHandlers.
       *
       * @param componentClass Class of the component for which the handle is
       *                       being requested.
       * @param configuration The configuration for this component.
       * @param componentManager The ComponentManager which will be managing
       *                         the Component.
       * @param context The current context object.
       * @param roleManager The current RoleManager.
       * @param logkitManager The current LogKitManager.
       *
       * @throws Exception If there were any problems obtaining a ComponentHandler
       */
      protected ComponentHandler getComponentHandler( final Class componentClass,
                                                      final Configuration configuration,
                                                      final ComponentManager componentManager,
                                                      final Context context,
                                                      final RoleManager roleManager,
                                                      final LogKitManager logkitManager )
          throws Exception
      {
          return ProfilerComponentHandler.getComponentHandler( componentClass,
                                                               configuration,
                                                               componentManager,
                                                               context,
                                                               roleManager,
                                                               logkitManager,
                                                               m_profilerManager );
      }
      
      /*---------------------------------------------------------------
       * ProfilerManageable Methods
       *-------------------------------------------------------------*/
      /**
       * Sets the ProfilerManager for child components.  Can be for special
       * purpose components, however it is used mostly internally.
       *
       * @param profilerManager The ProfilerManager for the component to use.
       */
      public void setProfilerManager( final ProfilerManager profilerManager )
      {
          m_profilerManager = profilerManager;
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/component/ProfilerDefaultComponentFactory.java
  
  Index: ProfilerDefaultComponentFactory.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.altprofile.component;
  
  import org.apache.avalon.excalibur.altprofile.Profilable;
  import org.apache.avalon.excalibur.altprofile.ProfilePoint;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManageable;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.component.DefaultComponentFactory;
  import org.apache.avalon.excalibur.component.RoleManageable;
  import org.apache.avalon.excalibur.component.RoleManager;
  import org.apache.avalon.excalibur.pool.ObjectFactory;
  import org.apache.avalon.excalibur.logger.LogKitManager;
  import org.apache.avalon.excalibur.logger.LogKitManageable;
  import org.apache.avalon.excalibur.collections.BucketMap;
  
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  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.parameters.Parameterizable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLoggable;
  import org.apache.avalon.framework.logger.Loggable;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.logger.LogKitLogger;
  import org.apache.avalon.framework.thread.ThreadSafe;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.Component;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  
  /**
   * Factory for Avalon Profilable components.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.0
   */
  public class ProfilerDefaultComponentFactory
      extends DefaultComponentFactory
  {
      private ProfilerManager m_profilerManager;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Construct a new component factory for the specified component.
       *
       * @param componentClass the class to instantiate (must have a default constructor).
       * @param configuration the <code>Configuration</code> object to pass to new instances.
       * @param componentManager the component manager to pass to <code>Composable</code>s.
       * @param context the <code>Context</code> to pass to <code>Contexutalizable</code>s.
       * @param roles the <code>RoleManager</code> to pass to <code>DefaultComponentSelector</code>s.
       * @param profilerManager the <code>ProfilerManager</code> to register the component with if
       *        it is a Profilable.
       */
      public ProfilerDefaultComponentFactory( final Class componentClass,
                                              final Configuration configuration,
                                              final ComponentManager componentManager,
                                              final Context context,
                                              final RoleManager roles,
                                              final LogKitManager logkit,
                                              final ProfilerManager profilerManager )
  
      {
          super( componentClass, configuration, componentManager, context, roles, logkit );
          
          m_profilerManager = profilerManager;
      }
  
      
      /*---------------------------------------------------------------
       * DefaultComponentFactory Methods
       *-------------------------------------------------------------*/
      /**
       * Called after a new component is initialized, but before it is started.  This was added
       *  to make it possible to implement the ProfilerComponentFactory without too much duplicate
       *  code.  WARNING:  Do not take advantage of this method as it will most likely be removed.
       */
      protected void postLogger( Object component, Configuration configuration )
          throws Exception
      {
          if ( component instanceof ProfilerManageable )
          {
              ((ProfilerManageable)component).setProfilerManager( m_profilerManager );
          }
      }
      
      /**
       * Called after a new component is initialized, but before it is started.  This was added
       *  to make it possible to implement the ProfilerComponentFactory without too much duplicate
       *  code.  WARNING:  Do not take advantage of this method as it will most likely be removed.
       */
      protected void postInitialize( Object component, Configuration configuration )
          throws Exception
      {
          if ( component instanceof Profilable )
          {
              getLogger().debug( "Doing profiler setup for: " + component );
              m_profilerManager.registerProfilable( (Profilable)component, configuration );
          }
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/AbstractProfileSample.java
  
  Index: AbstractProfileSample.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.altprofile.profiler;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * An AbstractProfileSample contains all of the functionality common to all
   *  ProfileSamples.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  abstract class AbstractProfileSample
      extends AbstractLogEnabled
      implements ProfileSample
  {
      /** The name of the new ProfileSample. */
      private String m_name;
      
      /** The sample interval of the new ProfileSample. */
      private long m_interval;
      
      /** The number of samples to store as history. */
      private int m_size;
      
      /** The description of the new ProfileSample. */
      private String m_description;
      
      /** The Descriptor for the ProfileSample. */
      private ProfileSampleDescriptor m_descriptor;
      
      /** 
       * The maximum amount of time between updates before history will be
       * wiped clean.
       */
      private long m_maxAge;
      
      /** The UNIX time of the beginning of the sample. */
      protected long m_time;
      
      /** The Index into the history arrays. */
      private int m_historyIndex;
      
      /** The Old half of the history array. */
      private int[] m_historyOld;
      
      /** The New half of the history array. */
      private int[] m_historyNew;
      
      /** List of registered ProfileSampleListeners. */
      private ArrayList m_listeners;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new AbstractProfileSample
       *
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.  Assumes that size is at least 1.
       * @param description The description of the new ProfileSample.
       */
      protected AbstractProfileSample( String name, long interval, int size, String description )
      {
          if ( interval < 1 )
          {
              throw new IllegalArgumentException( "interval must be at least 1." );
          }
          if ( size < 1 )
          {
              throw new IllegalArgumentException( "size must be at least 1." );
          }
          
          m_name = name;
          m_interval = interval;
          m_size = size;
          m_description = description;
          
          // Calculate the maxAge
          m_maxAge = m_size * m_interval;
          
          init();
          
          // Create the descriptor
          m_descriptor = new ProfileSampleDescriptor( this );
      }
      
      /*---------------------------------------------------------------
       * ProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * Returns the name of the sample.
       *
       * @return The name of the sample.
       */
      public final String getName()
      {
          return m_name;
      }
      
      /**
       * Returns the sample interval.  The period of each sample in millisends.
       *
       * @return The sample interval.
       */
      public final long getInterval()
      {
          return m_interval;
      }
      
      /**
       * Returns the number of samples in the sample history.
       *
       * @return The size of the sample history.
       */
      public final int getSize()
      {
          return m_size;
      }
      
      /**
       * Returns the description of the sample.
       *
       * @return The description of the sample.
       */
      public final String getDescription()
      {
          return m_description;
      }
      
      /**
       * Returns a Descriptor for the ProfileSample.
       *
       * @return A Descriptor for the ProfileSample.
       */
      public ProfileSampleDescriptor getDescriptor()
      {
          return m_descriptor;
      }
      
      /**
       * Obtain the value of the sample.  All samples are integers, so the profiled
       * objects must measure quantity (numbers of items), rate (items/period), time in
       * milliseconds, etc.
       *
       * @return The sample value.
       */
      public final int getValue()
      {
          boolean update;
          int value;
          long time;
          
          synchronized(this)
          {
              long now = System.currentTimeMillis();
              update = update( now );
              value = getValueInner();
              time = m_time;
          }
          
          if ( update )
          {
              updateListeners( value, time );
          }
          return value;
      }
      
      /**
       * Obtain the UNIX time of the beginning of the sample.
       *
       * @return The UNIX time of the beginning of the sample.
       */
      public final long getTime()
      {
          boolean update;
          int value;
          long time;
          
          synchronized(this)
          {
              long now = System.currentTimeMillis();
              update = update( now );
              value = getValueInner();
              time = m_time;
          }
          
          if ( update )
          {
              updateListeners( value, time );
          }
          return time;
      }
      
      /**
       * Obtains a static snapshot of the ProfileSample.
       *
       * @return A static snapshot of the ProfileSample.
       */
      public final ProfileSampleSnapshot getSnapshot()
      {
          synchronized(this)
          {
              long time = System.currentTimeMillis();
              update( time );
              
              return new ProfileSampleSnapshot(
                  m_name,
                  m_interval,
                  m_size,
                  m_time,
                  getHistorySnapshot() );
          }
      }
      
      /**
       * Registers a ProfileSampleListener with a ProfileSample given a name.
       *
       * @param listener The listener which should start receiving updates from the
       *                 ProfileSample.
       */
      public void addProfileSampleListener( ProfileSampleListener listener )
      {
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "A ProfileSampleListener was added to sample, " + m_name + " : " +
                  listener.getClass().getName() );
          }
          
          synchronized(this)
          {
              if ( m_listeners == null )
              {
                  m_listeners = new ArrayList();
              }
              m_listeners.add( listener );
          }
      }
      
      /**
       * Unregisters a ProfileSampleListener from a ProfileSample given a name.
       *
       * @param listener The listener which should stop receiving updates from the
       *                 ProfileSample.
       */
      public void removeProfileSampleListener( ProfileSampleListener listener )
      {
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "A ProfileSampleListener was removed from sample, " + m_name +
                  " : " + listener.getClass().getName() );
          }
          
          synchronized(this)
          {
              m_listeners.remove( listener );
              if ( m_listeners.size() == 0 )
              {
                  m_listeners = null;
              }
          }
      }
      
      /**
       * Notifies any listeners of a change.
       * <p>
       * Make sure that this is called OUTSIDE of a synchrinization block.
       *
       * @param value The new value.
       * @param time The time that the new value was set.
       */
      protected void updateListeners( int value, long time )
      {
          //System.out.println("updateListeners(" + value + ", " + time + ")");
          ProfileSampleListener[] listeners;
          synchronized(this)
          {
              if ( m_listeners == null )
              {
                  // Nobody is listening
                  return;
              }
              
              listeners = new ProfileSampleListener[ m_listeners.size() ];
              m_listeners.toArray( listeners );
          }
      
          // Call them outside of the synchronized block.
          for ( int i = 0; i < listeners.length; i++ )
          {
              listeners[i].setValue( getName(), value, time );
          }
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Initializes the sample
       */
      private void init()
      {
          // Calculate an interval time based on the current time by removing the modulous
          //  value of the current time. This will allign the intervals to the start of computer
          //  time.
          m_time = calculateSampleTime( System.currentTimeMillis() );
          
          // Create the arrays which will hold the history points.
          // History is build with m_value holding the current value and all previous values
          // spanning accross 2 arrays that switch places as time progresses.  This completely
          // removes the need to manage large lists or do array copies.
          // All history values are 0 initially.
          m_historyIndex = 0;
          m_historyOld = new int[ m_size - 1 ];
          m_historyNew = new int[ m_size - 1 ];
      }
      
      
      /**
       * Calculates the time of the sample which contains the specified time.
       *
       * @param time Time whose sample time is requested.
       */
      private long calculateSampleTime( long time )
      {
          return ( time / m_interval ) * m_interval;
      }
      
      /**
       * Gets the current value.  Does not update.
       * <p>
       * Should only be called when synchronized.
       *
       * @return The current value.
       */
      protected abstract int getValueInner();
      
      /**
       * The current sample has already been stored.  Reset the current sample
       *  and move on to the next.
       * <p>
       * Should only be called when synchronized.
       */
      protected abstract void advanceToNextSample();
      
      /**
       * Brings the ProfileSample's time up to date so that a new value can be added.
       * <p>
       * Should only be called when synchronized.
       *
       * @param time The time to which the ProfileSample should be brought up to date.
       *
       * @return True if listeners should be notified.
       */
      protected boolean update( long time )
      {
          //System.out.println("update(" + time + ")");
          // See if we are already up to date.
          if ( time - m_time >= m_interval )
          {
              // Needs to move to a new sample.
              if ( time - m_time >= m_maxAge )
              {
                  // The history is too old, reset the sample.
                  advanceToNextSample();
                  init();
              }
              else
              {
                  // Advance the history index.
                  while ( time - m_time >= m_interval )
                  {
                      // Store the current value into the end of the history.
                      m_historyNew[ m_historyIndex ] = getValueInner();
                      
                      // Advance to the next sample.
                      m_time += m_interval;
                      advanceToNextSample();
                      m_historyIndex++;
                      
                      if ( m_historyIndex >= m_size - 1 )
                      {
                          // Need to swap the history arrays
                          int[] tmp = m_historyOld;
                          m_historyOld = m_historyNew;
                          m_historyNew = tmp;
                          
                          // Reset the history index
                          m_historyIndex = 0;
                      }
                  }
              }
              return true;
          } else {
              return false;
          }
      }
      
      /**
       * Gets a snapshot of the samples.
       * <p>
       * Should only be called after an update when synchronized.
       *
       * @return A snapshot of the samples in the ProfileSample.
       */
      private int[] getHistorySnapshot()
      {
          // Create a new array to hold the snapshot of the history data.
          // This method is a little slow but normal collection of sample points is
          // extremely fast.
          int[] history = new int[m_size];
          
          int sizem1 = m_size - 1;
          
          if ( m_size > 1 )
          {
              // Copy samples from the old history first.
              if ( m_historyIndex < sizem1 )
              {
                  // Copy the last (size - 1 - historyIndex) samples from the old history.
                  System.arraycopy( m_historyOld, m_historyIndex, history, 0, sizem1 - m_historyIndex );
              }
              
              if ( m_historyIndex > 0 )
              {
                  // Copy the first (historyIndex) samples from the new history.
                  System.arraycopy( m_historyNew, 0, history, sizem1 - m_historyIndex, m_historyIndex );
              }
          }
          // Get the final sample from the current sample value.
          history[ m_size - 1] = getValueInner();
          
          return history;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/AbstractValueProfileSample.java
  
  Index: AbstractValueProfileSample.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.altprofile.profiler;
  
  /**
   * An AbstractValueProfileSample contains all of the functionality common
   *  to all ProfileSamples which represent a fixed value.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  abstract class AbstractValueProfileSample
      extends AbstractProfileSample
      implements ValueProfilePointListener
  {
      /** The sample value. */
      protected int m_value;
      
      /** The number of times that the value has been changed in this sample period. */
      protected int m_valueCount;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new AbstractValueProfileSample
       *
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.  Assumes that size is at least 1.
       * @param description The description of the new ProfileSample.
       */
      protected AbstractValueProfileSample( String name, long interval, int size, String description )
      {
          super( name, interval, size, description );
          
          // Set the current value to 0 initially.
          m_value = 0;
      }
      
      /*---------------------------------------------------------------
       * ProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * Returns the Type of the ProfilePoint which can use the sample.  This
       *  should be the same for all instances of a class.
       * <p>
       * This ProfileSample returns ProfilerManager.PROFILE_POINT_TYPE_VALUE
       *
       * @return The Type of the ProfilePoint which can use the sample.
       */
      public final int getProfilePointType()
      {
          return ProfilerManager.PROFILE_POINT_TYPE_VALUE;
      }
      
      /**
       * Obtain the value of the sample.  All samples are integers, so the profiled
       * objects must measure quantity (numbers of items), rate (items/period), time in
       * milliseconds, etc.
       * <p>
       * Should only be called when synchronized.
       *
       * @return The sample value.
       */
      public int getValueInner()
      {
          return m_value;
      }
      
      /*---------------------------------------------------------------
       * ValueProfilePointListener Methods
       *-------------------------------------------------------------*/
      /**
       * Called by a ValueProfilePoint whenever its value is set.
       *
       * @param profilePointName The key of ProfilePoint whose value was set.
       * @param value Value that was set.
       * @param time The time that the ProfilePoint was incremented.
       *
       * ValueProfilePoint
       */
      public void setValue( String profilePointName, int value, long time )
      {
          //System.out.println("AbstractValueProfileSample.setValue(" + profilePointName + ", " + value + ", " + time + ") : " + getName());
          setValueInner( value, time );
      }
      
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Sets the current value of the sample.
       *
       * @param value New sample value.
       * @param time Time that the new sample arrives.
       */
      protected abstract void setValueInner( int value, long time );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/AverageValueProfileSample.java
  
  Index: AverageValueProfileSample.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.altprofile.profiler;
  
  /**
   * A ProfileSample which stores the average value set during the sample
   *  period.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  class AverageValueProfileSample
      extends AbstractValueProfileSample
  {
      /** Total of all values seen during the sample period. */
      private long m_valueTotal;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new AverageValueProfileSample
       *
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.  Assumes that size is at least 1.
       * @param description The description of the new ProfileSample.
       */
      AverageValueProfileSample( String name, long interval, int size, String description )
      {
          super( name, interval, size, description );
      }
      
      /*---------------------------------------------------------------
       * AbstractProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * The current sample has already been stored.  Reset the current sample
       *  and move on to the next.
       * <p>
       * Should only be called when synchronized.
       */
      protected void advanceToNextSample()
      {
          // Leave the value as is so that it will propagate to the next sample
          //  if needed.  But reset the value count so that new values will not
          //  be affected by the old.
          m_valueCount = 0;
      }
      
      /*---------------------------------------------------------------
       * AbstractValueProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * Sets the current value of the sample.  The value will be set as the
       *  average of the new value and other values seen during the sample period.
       *
       * @param value New sample value.
       * @param time Time that the new sample arrives.
       */
      protected void setValueInner( int value, long time )
      {
          int sampleValue;
          long sampleTime;
          
          synchronized(this)
          {
              update( time );
              
              if ( m_valueCount > 0 )
              {
                  // Additional sample
                  m_valueCount++;
                  m_valueTotal += value;
                  m_value = (int)(m_valueTotal / m_valueCount);
              }
              else
              {
                  // First value of this sample.
                  m_valueCount = 1;
                  m_valueTotal = m_value = value;
              }
              sampleValue = m_value;
              sampleTime = m_time;
          }
          
          updateListeners( sampleValue, sampleTime );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/CounterProfilePointListener.java
  
  Index: CounterProfilePointListener.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.altprofile.profiler;
  
  /**
   * Objects which implement the CounterProfilePointListener interface can
   *  register themselves with ProfilePoint instances to receive updates when
   *  it is incremented.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface CounterProfilePointListener
  {
      /**
       * Called by a CounterProfilePoint whenever its value is incremented.
       *
       * @param profilePointKey The key of ProfilePoint which was incremented.
       * @param time The time that the ProfilePoint was incremented.
       */
      void increment( String profilePointKey, long time );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/CounterProfileSample.java
  
  Index: CounterProfileSample.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.altprofile.profiler;
  
  /**
   * A ProfileSample which stores the number of times that increment has been
   *  called during the sample period.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  class CounterProfileSample
      extends AbstractProfileSample
      implements CounterProfilePointListener
  {
      /** The count. */
      protected int m_count;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new CounterProfileSample
       *
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.  Assumes that size is at least 1.
       * @param description The description of the new ProfileSample.
       */
      CounterProfileSample( String name, long interval, int size, String description )
      {
          super( name, interval, size, description );
          
          // Set the current value to 0 initially.
          m_count = 0;
      }
      
      /*---------------------------------------------------------------
       * ProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * Returns the Type of the ProfilePoint which can use the sample.  This
       *  should be the same for all instances of a class.
       * <p>
       * This ProfileSample returns ProfilerManager.PROFILE_POINT_TYPE_COUNTER
       *
       * @return The Type of the ProfilePoint which can use the sample.
       */
      public final int getProfilePointType()
      {
          return ProfilerManager.PROFILE_POINT_TYPE_COUNTER;
      }
      
      /**
       * Obtain the value of the sample.  All samples are integers, so the profiled
       * objects must measure quantity (numbers of items), rate (items/period), time in
       * milliseconds, etc.
       *
       * @return The sample value.
       */
      public int getValueInner()
      {
          return m_count;
      }
      
      /*---------------------------------------------------------------
       * AbstractProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * The current sample has already been stored.  Reset the current sample
       *  and move on to the next.
       * <p>
       * Should only be called when synchronized.
       */
      protected void advanceToNextSample()
      {
          // Counts do not propagate, so always reset the count to 0.
          m_count = 0;
      }
      
      /*---------------------------------------------------------------
       * CounterProfilePointListener Methods
       *-------------------------------------------------------------*/
      /**
       * Called by a CounterProfilePoint whenever its value is incremented.
       *
       * @param profilePointName The name of ProfilePoint which was incremented.
       * @param time The time that the ProfilePoint was incremented.
       */
      public void increment( String profilePointName, long time )
      {
          //System.out.println("CounterProfileSample.increment(" + profilePointName + ", " + time + ") : " + getName() );
          increment( time );
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Increments the count.
       *
       * @param time Time that the count is incremented.
       */
      private void increment( long time )
      {
          int sampleValue;
          long sampleTime;
          
          synchronized(this)
          {
              update( time );
              
              m_count++;
              
              sampleValue = m_count;
              sampleTime = m_time;
          }
          
          updateListeners( sampleValue, sampleTime );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/DefaultProfilerManager.java
  
  Index: DefaultProfilerManager.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.altprofile.profiler;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  
  import org.apache.avalon.excalibur.altprofile.AbstractProfilePoint;
  import org.apache.avalon.excalibur.altprofile.CounterProfilePoint;
  import org.apache.avalon.excalibur.altprofile.Profilable;
  import org.apache.avalon.excalibur.altprofile.ProfilePoint;
  import org.apache.avalon.excalibur.altprofile.ValueProfilePoint;
  
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.component.ComponentException;
  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.logger.AbstractLogEnabled;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class DefaultProfilerManager
      extends AbstractLogEnabled
      implements Configurable, Initializable, Disposable, ProfilerManager, Profilable, Runnable
  {
      public static final String PROFILE_POINT_TOTAL_MEMORY = "total-memory";
      public static final String PROFILE_POINT_FREE_MEMORY = "free-memory";
      public static final String PROFILE_POINT_MEMORY = "memory";
      
      /** Configuration for the ProfileManager */
      private Configuration m_configuration;
      
      /** Semaphore for actions which must be synchronized */
      private Object m_semaphore = new Object();
      
      /** HashMap of all of the registered ProfilableProxies by their keys. */
      private HashMap m_profilableProxies = new HashMap();
      
      /** Optimized array of the ProfilableProxies. */
      private ProfilableProxy[] m_profilableProxyArray;
      
      /** Optimized array of the ProfilableDescriptors. */
      private ProfilableDescriptor[] m_profilableDescriptorArray;
      
      /**
       * Thread used to keep the profile points published by the ProfilerManager
       *  up to date.
       */
      private Thread m_runner;
      
      /** Profilable Name assigned to this Profilable */
      private String m_profilableName = "profiler";
      
      /** ProfilePoint used to profile the total memory. */
      private ValueProfilePoint m_totalMemoryProfilePoint;
      
      /** ProfilePoint used to profile the free memory. */
      private ValueProfilePoint m_freeMemoryProfilePoint;
      
      /** ProfilePoint used to profile the in use memory. */
      private ValueProfilePoint m_memoryProfilePoint;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      public DefaultProfilerManager()
      {
          // Initialize the Profiler elements.
          m_totalMemoryProfilePoint = new ValueProfilePoint( PROFILE_POINT_TOTAL_MEMORY );
          m_freeMemoryProfilePoint = new ValueProfilePoint( PROFILE_POINT_FREE_MEMORY );
          m_memoryProfilePoint = new ValueProfilePoint( PROFILE_POINT_MEMORY );
      }
      
      /*---------------------------------------------------------------
       * Configurable Methods
       *-------------------------------------------------------------*/
      /**
       * Initializes the configured profilables.
       *
       * @param configuration ProfilerManager configuration.
       *
       * @throws ConfigurationException If there are any configuration problems.
       */
      public void configure( Configuration configuration )
          throws ConfigurationException
      {
          synchronized(m_semaphore)
          {
              m_configuration = configuration;
              
              // Configure the profilables.
              Configuration profilablesConf = configuration.getChild( "profilables" );
              Configuration[] profilableConfs = profilablesConf.getChildren( "profilable" );
              for ( int i = 0; i < profilableConfs.length; i++ )
              {
                  Configuration profilableConf = profilableConfs[i];
                  String profilableName = profilableConf.getAttribute( "name" );
                  
                  ProfilableProxy profilableProxy = new ProfilableProxy( profilableName );
                  profilableProxy.enableLogging( getLogger() );
                  profilableProxy.configure( profilableConf );
                  m_profilableProxies.put( profilableName, profilableProxy );
                  
                  // Clear the optimized arrays
                  m_profilableProxyArray = null;
                  m_profilableDescriptorArray = null;
              }
          }
      }
      
      /*---------------------------------------------------------------
       * Initializable Methods
       *-------------------------------------------------------------*/
      /**
       * Initializes the ProfilerManager.
       *
       * @throws Exception If there were any problems initializing the object.
       */
      public void initialize()
          throws Exception
      {
          // Register the ProfilerManager as a Profilable.
          registerProfilableCommon( this, getProfilableName() );
          
          if ( m_runner == null )
          {
              m_runner = new Thread( this, "JVMProfilable" );
              m_runner.start();
          }
      }
      
      /*---------------------------------------------------------------
       * Disposable Methods
       *-------------------------------------------------------------*/
      /**
       * Disposes the ProfilerManager.
       */
      public void dispose()
      {
          if ( m_runner != null )
          {
              m_runner = null;
          }
      }
      
      /*---------------------------------------------------------------
       * ProfilerManager Methods
       *-------------------------------------------------------------*/
      /**
       * Returns a ProfilableDescriptor based on its name.
       *
       * @param profilableName Name of the Profilable being requested.
       *
       * @return A Descriptor of the requested Profilable.
       *
       * @throws NoSuchProfilableException If the specified Profilable does
       *                                   not exist.
       */
      public ProfilableDescriptor getProfilableDescriptor( String profilableName )
          throws NoSuchProfilableException
      {
          ProfilableProxy proxy = (ProfilableProxy)m_profilableProxies.get( profilableName );
          if ( proxy == null )
          {
              throw new NoSuchProfilableException(
                  "No profilable with name, " + profilableName + ", has been registered." );
          }
          
          return proxy.getDescriptor();
      }
      
      /**
       * Returns an array of Descriptors for the Profilables managed by this
       *  ProfilerManager.
       *
       * @return An array of Descriptors for the Profilables managed by this
       *  ProfilerManager.
       */
      public ProfilableDescriptor[] getProfilableDescriptors()
      {
          ProfilableDescriptor[] descriptors = m_profilableDescriptorArray;
          if ( descriptors == null )
          {
              descriptors = updateProfilableDescriptorArray();
          }
          return descriptors;
      }
      
      /**
       * Profilable to be registered with the profile manager.  Should be called
       *  happen whenever a Profilable is created.
       *
       * @param profilable Profilable to register with the ProfilerManager.
       * @param configuration The configuration of the Profilable.
       *
       * @throws Exception if there was a problem registering the Profilable.
       */
      public void registerProfilable( Profilable profilable, Configuration configuration )
          throws Exception
      {
          String profilableName = configuration.getAttribute( "profilable", null );
          
          // If the profilableName was not set, then profiling should not be enabled
          //  for the component.
          if ( profilableName == null )
          {
              return;
          }
          
          registerProfilableCommon( profilable, profilableName );
      }
      
      /*---------------------------------------------------------------
       * Profilable Methods
       *-------------------------------------------------------------*/
      /**
       * Sets the name for the Profilable.  The Profilable Name is used to
       *  uniquely identify the Profilable during the configuration of the
       *  Profiler and to gain access to a ProfilableDescriptor through a
       *  ProfilerManager.  The value should be a string which does not
       *  contain spaces or periods.
       * <p>
       * This value may be set by a parent Profilable, or by the ProfilerManager
       *  using the value of the 'profilable' attribute in the configuration
       *  of the component.
       *
       * @param name The name used to identify a Profilable.
       */
      public void setProfilableName( String name )
      {
          m_profilableName = name;
      }
      
      /**
       * Gets the name of the Profilable.  The Profilable Name is used to
       *  uniquely identify the Profilable during the configuration of the
       *  Profiler and to gain access to a ProfilableDescriptor through a
       *  ProfilerManager.  The value should be a string which does not 
       *  contain spaces or periods.
       *
       * @return The name used to identify a Profilable.
       */
      public String getProfilableName()
      {
          return m_profilableName;
      }
  
      /**
       * Obtain a reference to all the ProfilePoints that the Profilable
       * object wishes to expose.  All sampling is done directly through
       * the ProfilePoints as opposed to the Profilable interface.
       *
       * @return An array of the ProfilePoints available for profiling.
       *         Should never be null.  If there are no ProfilePoints, then
       *         EMPTY_PROFILE_POINT_ARRAY can be returned.  This should
       *         never be the case though unless there are child Profilables
       *         with ProfilePoints.
       */
      public ProfilePoint[] getProfilePoints()
      {
          return new ProfilePoint[]
          {
              m_totalMemoryProfilePoint,
              m_freeMemoryProfilePoint,
              m_memoryProfilePoint
          };
      }
  
      /**
       * Any Object which implements Profilable can also make use of other
       *  Profilable child objects.  This method is used to tell the Profiler
       *  about them.
       *
       * @return An array of child Profilables.  This method should never
       *         return null.  If there are no child Profilables, then
       *         EMPTY_PROFILABLE_ARRAY can be returned.
       */
      public Profilable[] getChildProfilables()
      {
          return Profilable.EMPTY_PROFILABLE_ARRAY;
      }
      
      /*---------------------------------------------------------------
       * Runnable Methods
       *-------------------------------------------------------------*/
      public void run()
      {
          while ( m_runner != null )
          {
              try
              {
                  Thread.sleep( 1000 );
                  
                  memoryProfilePoints();
              }
              catch ( Throwable t )
              {
                  getLogger().error( "Encountered an unexpected error.", t );
              }
          }
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Updates the Memory based Profile Points published by the ProfilerManager.
       */
      private void memoryProfilePoints()
      {
          // Avoid doing unneeded work if profile points are not being used.
          Runtime runtime = null;
          long totalMemory = -1;
          long freeMemory = -1;
          
          // Total Memory
          if ( m_totalMemoryProfilePoint.isActive() )
          {
              runtime = Runtime.getRuntime();
              totalMemory = runtime.totalMemory();
              m_totalMemoryProfilePoint.setValue( (int)totalMemory );
          }
          
          // Free Memory
          if ( m_freeMemoryProfilePoint.isActive() )
          {
              if ( runtime == null )
              {
                  runtime = Runtime.getRuntime();
              }
              freeMemory = runtime.freeMemory();
              m_freeMemoryProfilePoint.setValue( (int)freeMemory );
          }
          
          // In use Memory
          if ( m_memoryProfilePoint.isActive() )
          {
              if ( runtime == null )
              {
                  runtime = Runtime.getRuntime();
              }
              if ( totalMemory < 0 )
              {
                  totalMemory = runtime.totalMemory();
              }
              if ( freeMemory < 0 )
              {
                  freeMemory = runtime.freeMemory();
              }
              m_memoryProfilePoint.setValue( (int)(totalMemory - freeMemory) );
          }
      }
      
      /**
       * Common code to registered with the profile manager.
       *
       * @param profilable Profilable to register with the ProfilerManager.
       * @param profilableName Name of the Profilable.
       *
       * @throws Exception if there was a problem registering the Profilable.
       */
      private void registerProfilableCommon( Profilable profilable, String profilableName )
          throws Exception
      {
          getLogger().debug( "Registering Profilable: " + profilableName );
          
          synchronized(m_semaphore)
          {
              // If the profilable does not implement ThreadSafe, then it is possible that
              //  another one of its instance was already registered.  If so, then the
              //  ProfilePoints will all be the same.  The new instances still need to be
              //  registered however.
              ProfilableProxy profilableProxy =
                  (ProfilableProxy)m_profilableProxies.get( profilableName );
              if ( profilableProxy == null )
              {
                  // This is a Profilable that has not been seen before.
                  profilableProxy = new ProfilableProxy( profilableName );
                  profilableProxy.enableLogging( getLogger() );
                  // Do not call configure here because there is no configuration
                  //  for discovered profilables.
                  m_profilableProxies.put( profilableName, profilableProxy );
                  
                  // Recursively register all the ProfilePoints in this and any child Profilables.
                  registerProfilePoints( profilable, profilableProxy, profilableName );
              }
              else
              {
                  // Additional Profilable instance.  Possible that new ProfilePoints could be found.
                  registerProfilePoints( profilable, profilableProxy, profilableName );
              }
          }
      }
      
      /**
       * Updates the cached array of ProfilableProxies taking
       *  synchronization into account.
       *
       * @return An array of the ProfilableProxies.
       */
      private ProfilableProxy[] updateProfilableProxyArray()
      {
          synchronized(m_semaphore)
          {
              m_profilableProxyArray = new ProfilableProxy[ m_profilableProxies.size() ];
              m_profilableProxies.values().toArray( m_profilableProxyArray );
              
              return m_profilableProxyArray;
          }
      }
      
      /**
       * Updates the cached array of ProfilableDescriptors taking
       *  synchronization into account.
       *
       * @return An array of the ProfilableDescriptors.
       */
      private ProfilableDescriptor[] updateProfilableDescriptorArray()
      {
          synchronized(m_semaphore)
          {
              if ( m_profilableProxyArray == null )
              {
                  updateProfilableProxyArray();
              }
              
              m_profilableDescriptorArray =
                  new ProfilableDescriptor[ m_profilableProxyArray.length ];
              for ( int i = 0; i < m_profilableProxyArray.length; i++ )
              {
                  m_profilableDescriptorArray[i] = m_profilableProxyArray[i].getDescriptor();
              }
              
              return m_profilableDescriptorArray;			
          }
      }
      
      /**
       * Examines a profilable and Registers all of its ProfilePoints.
       * <p>
       * Only called when m_semaphore is locked.
       */
      private void registerProfilePoints( Profilable profilable,
                                          ProfilableProxy profilableProxy,
                                          String profilableName )
          throws Exception
      {
          // Loop over the ProfilePoints published by this Profilable
          ProfilePoint[] profilePoints = profilable.getProfilePoints();
          for ( int i = 0; i < profilePoints.length; i++ )
          {
              ProfilePoint profilePoint = profilePoints[i];
              String profilePointName =
                  profilableName + "." + profilePoint.getProfilePointName();
              
              getLogger().debug( "Registering ProfilePoint: " + profilePointName );
              
              // See if a proxy exists for the ProfilePoint yet.
              ProfilePointProxy proxy = profilableProxy.getProfilePointProxy( profilePointName );
              if ( proxy == null )
              {
                  proxy = new ProfilePointProxy( profilePointName );
                  
                  // Set the type of the new ProfilePointProxy depending on the
                  //  class of the actual ProfilePoint.
                  if ( profilePoint instanceof CounterProfilePoint )
                  {
                      proxy.setType( ProfilerManager.PROFILE_POINT_TYPE_COUNTER );
                  }
                  else if ( profilePoint instanceof ValueProfilePoint )
                  {
                      proxy.setType( ProfilerManager.PROFILE_POINT_TYPE_VALUE );
                  }
                  else
                  {
                      throw new ComponentException( "Encountered an unknown ProfilePoint type for " +
                          "the ProfilePoint with key, " + profilePointName + ": " +
                          profilePoint.getClass().getName() );
                  }
                  
                  // Store a reference to the proxy in the ProfilePoint.
                  ((AbstractProfilePoint)profilePoint).setProfilePointProxy( proxy );
                  
                  
                  profilableProxy.addProfilePointProxy( proxy );
              }
              else
              {
                  // Register the existing proxy with the ProfilePoint.  Make sure that the
                  //  type didn't change on us.
                  if ( profilePoint instanceof CounterProfilePoint )
                  {
                      switch ( proxy.getType() )
                      {
                      case ProfilerManager.PROFILE_POINT_TYPE_COUNTER:
                          // Type is the same.
                          // Store a reference to the proxy in the ProfilePoint.
                          ((AbstractProfilePoint)profilePoint).setProfilePointProxy( proxy );
                          break;
                          
                      case ProfilerManager.PROFILE_POINT_TYPE_NONE:
                          // Not yet set.  Created in configuration.
                          proxy.setType( ProfilerManager.PROFILE_POINT_TYPE_COUNTER );
                          
                          // Store a reference to the proxy in the ProfilePoint.
                          ((AbstractProfilePoint)profilePoint).setProfilePointProxy( proxy );
                          break;
                          
                      default:
                          throw new ComponentException(
                              "ProfilePoints of more than one type are assigned to name: " + 
                              profilePointName );
                      }
                  }
                  else if ( profilePoint instanceof ValueProfilePoint )
                  {
                      switch ( proxy.getType() )
                      {
                      case ProfilerManager.PROFILE_POINT_TYPE_VALUE:
                          // Type is the same.
                          // Store a reference to the proxy in the ProfilePoint.
                          ((AbstractProfilePoint)profilePoint).setProfilePointProxy( proxy );
                          break;
                          
                      case ProfilerManager.PROFILE_POINT_TYPE_NONE:
                          // Not yet set.  Created in configuration.
                          proxy.setType( ProfilerManager.PROFILE_POINT_TYPE_VALUE );
                          
                          // Store a reference to the proxy in the ProfilePoint.
                          ((AbstractProfilePoint)profilePoint).setProfilePointProxy( proxy );
                          break;
                          
                      default:
                          throw new ComponentException(
                              "ProfilePoints of more than one type are assigned to name: " + 
                              profilePointName );
                      }
                  }
                  else
                  {
                      throw new ComponentException( "Encountered an unknown ProfilePoint type for " +
                          "the ProfilePoint with name, " + profilePointName + ": " +
                          profilePoint.getClass().getName() );
                  }
              }
          }
  
          // Loop over the child Profilables and register their ProfilePoints as well.
          Profilable[] childProfilables = profilable.getChildProfilables();
          for ( int i = 0; i < childProfilables.length; i++ )
          {
              // Make sure that the child profilable name is set.
              if ( childProfilables[i].getProfilableName() == null )
              {
                  String msg = "The getProfilableNAme of a child Profilable returned null.  " +
                      "Instance of " + profilable.getClass().getName();
                  getLogger().debug( msg );
                  throw new ComponentException( msg );
              }
              
              String profilableChildName = profilableName + "." +
                  childProfilables[i].getProfilableName();
              
              registerProfilePoints( childProfilables[i], profilableProxy, profilableChildName );
          }
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/MaximumValueProfileSample.java
  
  Index: MaximumValueProfileSample.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.altprofile.profiler;
  
  /**
   * A ProfileSample which stores the maximum value set during the sample
   *  period.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  class MaximumValueProfileSample
      extends AbstractValueProfileSample
  {
      /** Last value set to the sample for use for sample periods where no value is set. */
      private int m_lastValue;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new MaximumValueProfileSample
       *
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.  Assumes that size is at least 1.
       * @param description The description of the new ProfileSample.
       */
      MaximumValueProfileSample( String name, long interval, int size, String description )
      {
          super( name, interval, size, description );
      }
      
      /*---------------------------------------------------------------
       * AbstractProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * The current sample has already been stored.  Reset the current sample
       *  and move on to the next.
       * <p>
       * Should only be called when synchronized.
       */
      protected void advanceToNextSample()
      {
          // Reset the value count and set the value to the last known value.
          m_value = m_lastValue;
          m_valueCount = 0;
      }
      
      /*---------------------------------------------------------------
       * AbstractValueProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * Sets the current value of the sample.  The value will be set as the
       *  sample value if it is the largest value seen during the sample period.
       *
       * @param value New sample value.
       * @param time Time that the new sample arrives.
       */
      protected void setValueInner( int value, long time )
      {
          boolean update;
          int sampleValue;
          long sampleTime;
          
          synchronized(this)
          {
              update = update( time );
              
              // Always store the last value to use for samples where a value is not set.
              m_lastValue = value;
              
              if ( m_valueCount > 0 )
              {
                  // Additional sample
                  m_valueCount++;
                  if ( value > m_value )
                  {
                      m_value = value;
                      update = true;
                  }
              }
              else
              {
                  // First value of this sample.
                  m_valueCount = 1;
                  m_value = value;
                  update = true;
              }
              
              sampleValue = m_value;
              sampleTime = m_time;
          }
          
          if ( update )
          {
              updateListeners( sampleValue, sampleTime );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/MinimumValueProfileSample.java
  
  Index: MinimumValueProfileSample.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.altprofile.profiler;
  
  /**
   * A ProfileSample which stores the minimum value set during the sample
   *  period.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  class MinimumValueProfileSample
      extends AbstractValueProfileSample
  {
      /** Last value set to the sample for use for sample periods where no value is set. */
      private int m_lastValue;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new MinimumValueProfileSample
       *
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.  Assumes that size is at least 1.
       * @param description The description of the new ProfileSample.
       */
      MinimumValueProfileSample( String name, long interval, int size, String description )
      {
          super( name, interval, size, description );
      }
      
      /*---------------------------------------------------------------
       * AbstractProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * The current sample has already been stored.  Reset the current sample
       *  and move on to the next.
       * <p>
       * Should only be called when synchronized.
       */
      protected void advanceToNextSample()
      {
          // Reset the value count and set the value to the last known value.
          m_value = m_lastValue;
          m_valueCount = 0;
      }
      
      /*---------------------------------------------------------------
       * AbstractValueProfileSample Methods
       *-------------------------------------------------------------*/
      /**
       * Sets the current value of the sample.  The value will be set as the
       *  sample value if it is the smallest value seen during the sample period.
       *
       * @param value New sample value.
       * @param time Time that the new sample arrives.
       */
      protected void setValueInner( int value, long time )
      {
          boolean update;
          int sampleValue;
          long sampleTime;
          
          synchronized(this)
          {
              update( time );
              
              // Always store the last value to use for samples where a value is not set.
              m_lastValue = value;
              
              if ( m_valueCount > 0 )
              {
                  // Additional sample
                  m_valueCount++;
                  if ( value < m_value )
                  {
                      m_value = value;
                      update = true;
                  }
              }
              else
              {
                  // First value of this sample.
                  m_valueCount = 1;
                  m_value = value;
              }
              
              sampleValue = m_value;
              sampleTime = m_time;
                  update = true;
          }
          
          if ( update )
          {
              updateListeners( sampleValue, sampleTime );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/NoSuchProfilableException.java
  
  Index: NoSuchProfilableException.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.altprofile.profiler;
  
  /**
   * Thrown when a Profilable can not be found.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class NoSuchProfilableException
      extends RuntimeException
  {
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Construct a new NoSuchProfilableException instance.
       *
       * @param message The detail message for this exception.
       */
      public NoSuchProfilableException( String message )
      {
          super( message );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/NoSuchProfilePointException.java
  
  Index: NoSuchProfilePointException.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.altprofile.profiler;
  
  /**
   * Thrown when a ProfilePoint can not be found.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class NoSuchProfilePointException
      extends RuntimeException
  {
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Construct a new NoSuchProfilePointException instance.
       *
       * @param message The detail message for this exception.
       */
      public NoSuchProfilePointException( String message )
      {
          super( message );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/NoSuchProfileSampleException.java
  
  Index: NoSuchProfileSampleException.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.altprofile.profiler;
  
  /**
   * Thrown when a ProfileSample can not be found.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class NoSuchProfileSampleException
      extends RuntimeException
  {
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Construct a new NoSuchProfileSampleException instance.
       *
       * @param message The detail message for this exception.
       */
      public NoSuchProfileSampleException( String message )
      {
          super( message );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfilableDescriptor.java
  
  Index: ProfilableDescriptor.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.altprofile.profiler;
  
  import java.util.HashMap;
  
  /**
   * Describes a Profilable and acts as a Proxy to protect the original
   *  Profilable.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfilableDescriptor
  {
      /** ProfilableProxy being described. */
      private ProfilableProxy m_profilableProxy;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new ProfilableDescriptor.
       *
       * @param profilableProxy ProfilableProxy being described.
       */
      ProfilableDescriptor( ProfilableProxy profilableProxy )
      {
          m_profilableProxy = profilableProxy;
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Returns true if the Profilable was configured in the profilables
       *  section of the configuration.
       *
       * @return True if configured.
       */
      public boolean isConfigured()
      {
          return m_profilableProxy.isConfigured();
      }
      
      /**
       * Gets the name for the Profilable.  The Profilable Name is used to
       *  uniquely identify the Profilable during the configuration of the
       *  Profiler and to gain access to a ProfilableDescriptor through a
       *  ProfilerManager.
       *
       * @return The name used to identify a Profilable.
       */
      public String getName() 
      {
          return m_profilableProxy.getName();
      }
      
      /**
       * Gets the description of the Profilable.
       *
       * @return The description of the Profilable.
       */
      public String getDescription()
      {
          return m_profilableProxy.getDescription();
      }
      
      /**
       * Returns a ProfilePointDescriptor based on its name.
       *
       * @param profilePointName Name of the ProfilePoint being requested.
       *
       * @return A Descriptor of the requested ProfilePoint.
       *
       * @throws NoSuchProfilePointException If the specified ProfilePoint does
       *                                     not exist.
       */
      public ProfilePointDescriptor getProfilePointDescriptor( String profilePointName )
          throws NoSuchProfilePointException
      {
          ProfilePointProxy profilePointProxy =
              m_profilableProxy.getProfilePointProxy( profilePointName );
          if ( profilePointProxy == null )
          {
              throw new NoSuchProfilePointException( "The requested ProfilePoint does not exist." );
          }
          
          return profilePointProxy.getDescriptor();
      }
      
      /**
       * Returns an array of Descriptors for the ProfilePoints registered by this
       *  Profilable.
       *
       * @return An array of Descriptors for the ProfilePoints registered by this
       *  Profilable.
       */
      public ProfilePointDescriptor[] getProfilePointDescriptors()
      {
  		return m_profilableProxy.getProfilePointDescriptors();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfilableProxy.java
  
  Index: ProfilableProxy.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.altprofile.profiler;
  
  import java.util.HashMap;
  
  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.logger.AbstractLogEnabled;
  
  /**
   * A ProfilableProxy makes it easy for the ProfilerManager to manage
   *  Profilables and their ProfilePoints.
   * <p>
   * Not Synchronized.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  class ProfilableProxy
  	extends AbstractLogEnabled
  	implements Configurable
  {
      /** Configured flag. */
      private boolean m_configured;
      
      /** The name used to identify a Profilable. */
      private String m_name;
      
      /** The description of the Profilable. */
      private String m_description;
  	
  	/** The Descriptor for the Profilable. */
  	private ProfilableDescriptor m_descriptor;
      
      /** Map of the ProfilePointProxies owned by this ProfilableProxy. */
      private HashMap m_profilePointProxies = new HashMap();
      
  	/** Optimized array of the ProfilePointProxies. */
      private ProfilePointProxy[] m_profilePointProxyArray;
  	
  	/** Optimized array of the ProfilePointDescriptors. */
  	private ProfilePointDescriptor[] m_profilePointDescriptorArray;
  	
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new ProfilableProxy.
  	 *
  	 * @param name The name used to identify a Profilable.
  	 */
      ProfilableProxy( String name )
      {
  		// Default description equals the name in case it is not set later.
  		m_description = m_name = name;
  		
  		// Create the descriptor
  		m_descriptor = new ProfilableDescriptor( this );
  	}
  	
  	/*---------------------------------------------------------------
  	 * Configurable Methods
  	 *-------------------------------------------------------------*/
  	/**
  	 * Configures the Profilable.  Called from the ProfilerManager's
  	 *  configure method.  The class does not need to be configured to
  	 *  function correctly.
  	 *
  	 * @param configuration Profilable configuration element from the
  	 *                      ProfilerManager's configuration.
  	 *
  	 * @throws ConfigurationException If there are any configuration problems.
  	 */
  	public void configure( Configuration configuration )
  		throws ConfigurationException
  	{
  		synchronized(this)
  		{
  			// The description is optional
  			m_description = configuration.getAttribute( "description", m_name );
  			
  			if ( getLogger().isDebugEnabled() )
  			{
  				getLogger().debug( "Configuring Profilable: " + m_name + " as \"" +
  					m_description + "\"" );
  			}
  			
  			m_configured = true;
  			
  			// Configure any ProfilePoints
  			Configuration[] profilePointConfs = configuration.getChildren( "profile-point" );
  			for ( int i = 0; i < profilePointConfs.length; i++ )
  			{
  				Configuration profilePointConf = profilePointConfs[i];
  				String profilePointName = m_name + "." + profilePointConf.getAttribute( "name" );
  				
  				ProfilePointProxy profilePointProxy = new ProfilePointProxy( profilePointName );
  				profilePointProxy.enableLogging( getLogger() );
  				profilePointProxy.configure( profilePointConf );
  				m_profilePointProxies.put( profilePointName, profilePointProxy );
  				
  				// Clear the optimized arrays
  				m_profilePointProxyArray = null;
  				m_profilePointDescriptorArray = null;
  			}
  		}
  	}
  		
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      /**
  	 * Returns true if the profilable was configured in the profilables
  	 *  section of the configuration.
  	 *
  	 * @return True if configured.
  	 */
      boolean isConfigured()
      {
          return m_configured;
      }
      
      /**
  	 * Gets the name for the Profilable.  The Profilable Name is used to
  	 *  uniquely identify the Profilable during the configuration of the
  	 *  Profiler and to gain access to a ProfilableDescriptor through a
  	 *  ProfilerManager.
  	 *
  	 * @return The name used to identify a Profilable.
  	 */
      String getName() 
      {
          return m_name;
      }
      
      /**
  	 * Sets the description for the profilable object.  This description will
  	 *  be set during the configuration of the profiler if a configuration
  	 *  exists for this Profilable.
  	 *
  	 * @param description The description of the Profilable.
  	 */
      void setDescription( String description )
      {
          m_description = description;
      }
      
      /**
  	 * Gets the description of the Profilable.
  	 *
  	 * @return The description of the Profilable.
  	 */
      String getDescription()
      {
          return m_description;
      }
      
  	/**
  	 * Returns a Descriptor for the Profilable.
  	 *
  	 * @return A Descriptor for the Profilable.
  	 */
  	ProfilableDescriptor getDescriptor()
  	{
  		return m_descriptor;
  	}
  	
  	/**
  	 * Adds a ProfilePointProxy to the Profilable.  This method will be
  	 *  called during the configuration phase of the Profiler if an element
  	 *  defining the ProfilePoint exists, or if the ProfilePoint registers
  	 *  itself with the ProfilerManager as it is running.
  	 * <p>
  	 * This method should never be called for ProfilePoints which have already
  	 *  been added.
  	 *
  	 * @param profilePointProxy ProfilePointProxy to be added.
  	 */
  	void addProfilePointProxy( ProfilePointProxy profilePointProxy )
  	{
  		synchronized(this)
  		{
  			m_profilePointProxies.put( profilePointProxy.getName(), profilePointProxy );
  			
  			// Clear the optimized arrays
  			m_profilePointProxyArray = null;
  			m_profilePointDescriptorArray = null;
  		}
  	}
  	
      /**
  	 * Returns a ProfilePointProxy based on its name.
  	 *
  	 * @param profilePointName Name of the ProfilePoint being requested.
  	 *
  	 * @return The requested ProfilePointProxy or null if does not exist.
  	 */
      ProfilePointProxy getProfilePointProxy( String profilePointName )
      {
          synchronized(this)
          {
              return (ProfilePointProxy)m_profilePointProxies.get( profilePointName );
          }
      }
      
      /**
  	 * Returns an array of Proxies to the ProfilePoints in the Profilable.
  	 *
  	 * @return An array of Proxies to the ProfilePoints in the Profilable.
  	 */
      ProfilePointProxy[] getProfilePointProxies()
      {
  		ProfilePointProxy[] proxies = m_profilePointProxyArray;
  		if ( proxies == null )
  		{
  			proxies = updateProfilePointProxyArray();
  		}
  		return proxies;
      }
  	
  	/**
  	 * Returns an array of Descriptors for the ProfilePoints in the Profilable.
  	 *
  	 * @return An array of Descriptors for the ProfilePoints in the Profilable.
  	 */
  	ProfilePointDescriptor[] getProfilePointDescriptors()
  	{
  		ProfilePointDescriptor[] descriptors = m_profilePointDescriptorArray;
  		if ( descriptors == null )
  		{
  			descriptors = updateProfilePointDescriptorArray();
  		}
  		return descriptors;
  	}
  	
  	/**
  	 * Updates the cached array of ProfilePointProxies taking
  	 *  synchronization into account.
  	 *
  	 * @return An array of the ProfilePointProxies.
  	 */
  	private ProfilePointProxy[] updateProfilePointProxyArray()
  	{
  		synchronized(this)
  		{
  			m_profilePointProxyArray = new ProfilePointProxy[ m_profilePointProxies.size() ];
  			m_profilePointProxies.values().toArray( m_profilePointProxyArray );
  			
  			return m_profilePointProxyArray;
  		}
  	}
  	
  	/**
  	 * Updates the cached array of ProfilePointDescriptors taking
  	 *  synchronization into account.
  	 *
  	 * @return An array of the ProfilePointDescriptors.
  	 */
  	private ProfilePointDescriptor[] updateProfilePointDescriptorArray()
  	{
  		synchronized(this)
  		{
  			if ( m_profilePointProxyArray == null )
  			{
  				updateProfilePointProxyArray();
  			}
  			
  			m_profilePointDescriptorArray =
  				new ProfilePointDescriptor[ m_profilePointProxyArray.length ];
  			for ( int i = 0; i < m_profilePointProxyArray.length; i++ )
  			{
  				m_profilePointDescriptorArray[i] = m_profilePointProxyArray[i].getDescriptor();
  			}
  			
  			return m_profilePointDescriptorArray;
  		}
  	}
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfilePointDescriptor.java
  
  Index: ProfilePointDescriptor.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.altprofile.profiler;
  
  import java.util.HashMap;
  
  /**
   * Describes a ProfilePoint and acts as a Proxy to protect the original
   *  ProfilePoint.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfilePointDescriptor
  {
      /** ProfilePointProxy being described. */
      private ProfilePointProxy m_profilePointProxy;
      
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new ProfilePointDescriptor.
  	 *
  	 * @param profilePointProxy ProfilePointProxy being described.
  	 */
      ProfilePointDescriptor( ProfilePointProxy profilePointProxy )
      {
          m_profilePointProxy = profilePointProxy;
      }
      
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      /**
  	 * Returns true if the ProfilePoint was configured in the profilables
  	 *  section of the configuration.
  	 *
  	 * @return True if configured.
  	 */
      public boolean isConfigured()
      {
          return m_profilePointProxy.isConfigured();
      }
      
      /**
  	 * Gets the name for the ProfilePoint.  The ProfilePoint Name is used to
  	 *  uniquely identify the ProfilePoint during the configuration of the
  	 *  Profiler.  The value should be a string which does not contain spaces
  	 *  or periods.
  	 *
  	 * @return The name used to identify a ProfilePoint.
  	 */
      public String getName() 
      {
          return m_profilePointProxy.getName();
      }
      
      /**
  	 * Gets the description of the ProfilePoint.
  	 *
  	 * @return The description of the ProfilePoint.
  	 */
      public String getDescription()
      {
          return m_profilePointProxy.getDescription();
      }
      
  	/**
  	 * Returns the type of the ProfilePoint.
  	 *
  	 * @return The type of the ProfilePoint.
  	 */
  	public int getType()
  	{
  		return m_profilePointProxy.getType();
  	}
  	
  	/**
  	 * Adds a CounterProfilePointListener to the list of listeners which will
  	 *  receive updates of the value of the ProfilePoint.
  	 *
  	 * @param listener CounterProfilePointListener which will start receiving
  	 *                 profile updates.
  	 *
  	 * @throws IllegalStateException If the ProfilePoint's type is not
  	 *         ProfilerManager.PROFILE_POINT_TYPE_COUNTER.
  	 */
  	public void addCounterProfilePointListener( CounterProfilePointListener listener )
  	{
  		m_profilePointProxy.addCounterProfilePointListener( listener );
  	}
  	
  	/**
  	 * Removes a ProfilePointListener from the list of listeners which will
  	 *  receive profile events.
  	 *
  	 * @param listener ProfilePointListener which will stop receiving profile
  	 *                 events.
  	 *
  	 * @throws IllegalStateException If the ProfilePoint's type is not
  	 *         ProfilerManager.PROFILE_POINT_TYPE_COUNTER.
  	 */
  	public void removeCounterProfilePointListener( CounterProfilePointListener listener )
  	{
  		m_profilePointProxy.removeCounterProfilePointListener( listener );
  	}
  	
  	/**
  	 * Adds a ValueProfilePointListener to the list of listeners which will
  	 *  receive updates of the value of the ProfilePoint.
  	 *
  	 * @param listener ValueProfilePointListener which will start receiving
  	 *                 profile updates.
  	 *
  	 * @throws IllegalStateException If the ProfilePoint's type is not
  	 *         ProfilerManager.PROFILE_POINT_TYPE_VALUE.
  	 */
  	public void addValueProfilePointListener( ValueProfilePointListener listener )
  	{
  		m_profilePointProxy.addValueProfilePointListener( listener );
  	}
  		
  	/**
  	 * Removes a ProfilePointListener from the list of listeners which will
  	 *  receive profile events.
  	 *
  	 * @param listener ProfilePointListener which will stop receiving profile
  	 *                 events.
  	 *
  	 * @throws IllegalStateException If the ProfilePoint's type is not
  	 *         ProfilerManager.PROFILE_POINT_TYPE_VALUE.
  	 */
  	void removeValueProfilePointListener( ValueProfilePointListener listener )
  	{
  		m_profilePointProxy.removeValueProfilePointListener( listener );
  	}
  	
      /**
  	 * Returns a ProfileSampleDescriptor based on its name.
  	 *
  	 * @param profileSampleName Name of the ProfileSample being requested.
  	 *
  	 * @return A Descriptor of the requested ProfileSample.
  	 *
  	 * @throws NoSuchProfileSampleException If the specified ProfileSample
  	 *                                      does not exist.
  	 */
      public ProfileSampleDescriptor getProfileSampleDescriptor( String profileSampleName )
          throws NoSuchProfileSampleException
      {
          ProfileSample profileSample =
              m_profilePointProxy.getProfileSample( profileSampleName );
          if ( profileSample == null )
          {
              throw new NoSuchProfileSampleException( "The requested ProfileSample does not exist." );
          }
          
          return profileSample.getDescriptor();
      }
      
      /**
  	 * Returns an array of Descriptors for the ProfileSamples configured for this
  	 *  ProfilePoint.
  	 *
  	 * @return An array of Descriptors for the ProfileSamples configured for this
  	 *  ProfilePoint.
  	 */
      public ProfileSampleDescriptor[] getProfileSampleDescriptors()
      {
  		return m_profilePointProxy.getProfileSampleDescriptors();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfilePointProxy.java
  
  Index: ProfilePointProxy.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.altprofile.profiler;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  
  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.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  
  /**
   * Profilables which do not implement ThreadSafe may have multiple instances
   *  created by the ComponentManager.  Each of these ProfilePoints will share
   *  a common key and are profiled as a group.  The ProfilePointProxy is used
   *  make it easy for the ProfilerManager to control groups of ProfilePoints
   *  as one.
   * <p>
   * The type of a ProfilePoint can not be determined at configuration time.
   *  It is resolved when the Profilable actually registers the ProfilePoint.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfilePointProxy
      extends AbstractLogEnabled
      implements Configurable
  {
      /** Configured flag. */
      private boolean m_configured;
      
      /** The name used to identify a ProfilePoint. */
      private String m_name;
      
      /** The description of the ProfilePointe. */
      private String m_description;
      
      /** The Descriptor for the ProfilePoint. */
      private ProfilePointDescriptor m_descriptor;
      
      /** Type of the ProfilePoint */
      private int m_type;
      
      /** List of registered Counter/ValueProfilePointListeners. */
      private ArrayList m_listeners;
      
      /** Map of the maintained ProfileSamples. */
      private HashMap m_samples = new HashMap();
      
      /** Optimized array of the ProfileSamples. */
      private ProfileSample[] m_sampleArray;
      
      /** Optimized array of the ProfileSampleDescriptors. */
      private ProfileSampleDescriptor[] m_sampleDescriptorArray;
      
      /** Child logger to use for logging of new values. */
      private Logger m_valueLogger;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new ProfilePointProxy.
       *
       * @param name The name used to identify a ProfilePoint.
       */
      ProfilePointProxy( String name )
      {
          // Default description equals the name in case it is not set later.
          m_description = m_name = name;
          
          // Create the descriptor
          m_descriptor = new ProfilePointDescriptor( this );
      }
      
      /*---------------------------------------------------------------
       * LogEnabled Methods
       *-------------------------------------------------------------*/
      public void enableLogging( Logger logger )
      {
          super.enableLogging( logger );
          
          // Create a child logger for logging setValue and increment calls so
          //  that they can be filtered out.
          m_valueLogger = logger.getChildLogger( "values" );
      }
      
      /*---------------------------------------------------------------
       * Configurable Methods
       *-------------------------------------------------------------*/
      /**
       * Configures the ProfilePoint.  Called from the ProfilerManager's
       *  configure method.  The class does not need to be configured to
       *  function correctly.
       *
       * @param configuration ProfilePoint configuration element from the
       *                      ProfilerManager's configuration.
       *
       * @throws ConfigurationException If there are any configuration problems.
       */
      public void configure( Configuration configuration )
          throws ConfigurationException
      {
          synchronized(this)
          {
              // The description is optional
              m_description = configuration.getAttribute( "description", m_name );
              
              if ( getLogger().isDebugEnabled() )
              {
                  getLogger().debug( "Configuring ProfilePoint: " + m_name + " as \"" +
                      m_description + "\"" );
              }
              
              m_configured = true;
              
              // Configure any Samples
              Configuration[] sampleConfs = configuration.getChildren( "sample" );
              for ( int i = 0; i < sampleConfs.length; i++ )
              {
                  Configuration sampleConf = sampleConfs[i];
                  
                  String sampleType = sampleConf.getAttribute( "type" );
                  long sampleInterval = sampleConf.getAttributeAsLong( "interval" );
                  int sampleSize = sampleConf.getAttributeAsInteger( "size", 1 );
                  
                  // Build the sample name from its attributes.  This makes it
                  //  possible to avoid forcing the user to maintain a name as well.
                  String sampleName = m_name + "." + sampleType + "." + 
                      sampleInterval + "." + sampleSize;
                  
                  String sampleDescription = sampleConf.getAttribute( "description", sampleName );
                  
                  if ( getLogger().isDebugEnabled() )
                  {
                      getLogger().debug( "Configuring ProfileSample: " + sampleName + 
                          " as \"" + sampleDescription + "\"" );
                  }
                  
                  ProfileSample profileSample = ProfileSampleFactory.getProfileSample(
                      sampleType, sampleName, sampleInterval, sampleSize, sampleDescription );
                  profileSample.enableLogging( getLogger() );
                  
                  addProfileSample( profileSample );
                  /*			
                  m_samples.put( sampleName, profileSample );
                  
                  // Clear the optimized arrays
                  m_sampleArray = null;
                  m_sampleDescriptorArray = null;
                  */
              }
          }
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Returns true if the ProfilePoint was configured in the profilables
       *  section of the configuration.
       *
       * @return True if configured.
       */
      boolean isConfigured()
      {
          return m_configured;
      }
      
      /**
       * Gets the name for the ProfilePoint.  The ProfilePoint Name is used to
       *  uniquely identify the ProfilePoint during the configuration of the
       *  Profiler and to gain access to a ProfilePointDescriptor through a
       *  ProfilerManager.
       *
       * @return The name used to identify a Profilable.
       */
      String getName() 
      {
          return m_name;
      }
      
      /**
       * Sets the description for the ProfilePoint.  This description will
       *  be set during the configuration of the profiler if a configuration
       *  exists for this ProfilePoint.
       *
       * @param description The description of the ProfilePoint.
       */
      void setDescription( String description )
      {
          m_description = description;
      }
      
      /**
       * Gets the description of the ProfilePoint.
       *
       * @return The description of the ProfilePoint.
       */
      String getDescription()
      {
          return m_description;
      }
      
      /**
       * Returns a Descriptor for the ProfilePoint.
       *
       * @return A Descriptor for the ProfilePoint.
       */
      ProfilePointDescriptor getDescriptor()
      {
          return m_descriptor;
      }
      
      /**
       * Set the type of the ProfilePoint.  Once set, the type can not be changed.
       *
       * @param type Type of the ProfilePoint.
       */
      void setType( int type )
      {
          synchronized(this)
          {
              if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_NONE )
              {
                  throw new IllegalStateException( "Type already set." );
              }
              switch ( type )
              {
              case ProfilerManager.PROFILE_POINT_TYPE_COUNTER:
              case ProfilerManager.PROFILE_POINT_TYPE_VALUE:
                  m_type = type;
                  break;
              default:
                  throw new IllegalStateException( type + " is not a valid type." );
              }
          }
      }
      
      /**
       * Returns the type of the ProfilePoint.
       *
       * @return The type of the ProfilePoint.
       */
      int getType()
      {
          return m_type;
      }
      
      /**
       * Used by classes being profiles so that they can avoid unnecessary
       *  code when the data from a ProfilePoint is not being used.
       *
       * @returns True if listeners are registered with the ProfilePoint.
       */
      public boolean isActive() {
          return m_listeners != null;
      }
      
      /**
       * Adds a CounterProfilePointListener to the list of listeners which will
       *  receive updates of the value of the ProfilePoint.
       *
       * @param listener CounterProfilePointListener which will start receiving
       *                 profile updates.
       *
       * @throws IllegalStateException If the ProfilePoint's type is not
       *         ProfilerManager.PROFILE_POINT_TYPE_COUNTER.
       */
      void addCounterProfilePointListener( CounterProfilePointListener listener )
      {
          if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_COUNTER )
          {
              // Type is not correct.
              throw new IllegalStateException(
                  "The proxy is not configured to handle CounterProfilePoints." );
          }
          
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "A CounterProfilePointListener was added to profile point, " + m_name +
                  " : " + listener.getClass().getName() );
          }
          
          synchronized(this)
          {
              if ( m_listeners == null )
              {
                  m_listeners = new ArrayList();
              }
              m_listeners.add( listener );
          }
      }
      
      /**
       * Removes a ProfilePointListener from the list of listeners which will
       *  receive profile events.
       *
       * @param listener ProfilePointListener which will stop receiving profile
       *                 events.
       *
       * @throws IllegalStateException If the ProfilePoint's type is not
       *         ProfilerManager.PROFILE_POINT_TYPE_COUNTER.
       */
      void removeCounterProfilePointListener( CounterProfilePointListener listener )
      {
          if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_COUNTER )
          {
              // Type is not correct.
              throw new IllegalStateException(
                  "The proxy is not configured to handle CounterProfilePoints." );
          }
          
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "A CounterProfilePointListener was removed from profile point, " + 
                  m_name + " : " + listener.getClass().getName() );
          }
          
          synchronized(this)
          {
              m_listeners.remove( listener );
              if ( m_listeners.size() == 0 )
              {
                  m_listeners = null;
              }
          }
      }
      
      /*
       * Increments the ProfilePoint.  This method is optimized to be extremely
       *  light weight when there are no registered CounterProfilePointListeners.
       */
      public void increment()
      {
          if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_COUNTER )
          {
              // Type is not correct.
              throw new IllegalStateException(
                  "The proxy is not configured to handle CounterProfilePoints." );
          }
          
          // Check to see if there are any listeners outside of a synchronization
          //  block to see if there is any reason to continue.
          if ( m_listeners != null )
          {
              if ( m_valueLogger.isDebugEnabled() )
              {
                  m_valueLogger.debug( "increment() called for ProfilePoint, " + m_name );
              }
              
              synchronized(this)
              {
                  // Check m_listeners again because it could have been set to null.
                  if ( m_listeners != null )
                  {
                      long time = System.currentTimeMillis();
                      for ( Iterator iter = m_listeners.iterator(); iter.hasNext(); )
                      {
                          CounterProfilePointListener listener =
                              (CounterProfilePointListener)iter.next();
                          listener.increment( getName(), time );
                      }
                  }
              }
          }
      }
      
      /**
       * Adds a ValueProfilePointListener to the list of listeners which will
       *  receive updates of the value of the ProfilePoint.
       *
       * @param listener ValueProfilePointListener which will start receiving
       *                 profile updates.
       *
       * @throws IllegalStateException If the ProfilePoint's type is not
       *         ProfilerManager.PROFILE_POINT_TYPE_VALUE.
       */
      void addValueProfilePointListener( ValueProfilePointListener listener )
      {
          if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_VALUE )
          {
              // Type is not correct.
              throw new IllegalStateException(
                  "The proxy is not configured to handle ValueProfilePoints." );
          }
          
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "A ValueProfilePointListener was added to profile point, " + m_name +
                  " : " + listener.getClass().getName() );
          }
          
          synchronized(this)
          {
              if ( m_listeners == null )
              {
                  m_listeners = new ArrayList();
              }
              m_listeners.add( listener );
          }
      }
      
      /**
       * Removes a ProfilePointListener from the list of listeners which will
       *  receive profile events.
       *
       * @param listener ProfilePointListener which will stop receiving profile
       *                 events.
       *
       * @throws IllegalStateException If the ProfilePoint's type is not
       *         ProfilerManager.PROFILE_POINT_TYPE_VALUE.
       */
      void removeValueProfilePointListener( ValueProfilePointListener listener )
      {
          if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_VALUE )
          {
              // Type is not correct.
              throw new IllegalStateException(
                  "The proxy is not configured to handle ValueProfilePoints." );
          }
          
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "A ValueProfilePointListener was removed from profile point, " + m_name +
                  " : " + listener.getClass().getName() );
          }
          
          synchronized(this)
          {
              m_listeners.remove( listener );
              if ( m_listeners.size() == 0 )
              {
                  m_listeners = null;
              }
          }
      }
      
      /**
       * Sets the current value of the ProfilePoint.  This method is optimized
       *  to be extremely light weight when there are no registered
       *  ValueProfilePointListeners.
       *
       * @param value The new value for the ProfilePoint.
       */
      public void setValue( int value )
      {
          if ( m_type != ProfilerManager.PROFILE_POINT_TYPE_VALUE )
          {
              // Type is not correct.
              throw new IllegalStateException(
                  "The proxy is not configured to handle ValueProfilePoints." );
          }
          
          // Check to see if there are any listeners outside of a synchronization
          //  block to see if there is any reason to continue.
          if ( m_listeners != null )
          {
              if ( m_valueLogger.isDebugEnabled() )
              {
                  m_valueLogger.debug( "setValue( " + value + " ) called for ProfilePoint, " + m_name );
              }
              
              synchronized(this)
              {
                  // Check m_listeners again because it could have been set to null.
                  if ( m_listeners != null )
                  {
                      long time = System.currentTimeMillis();
                      for ( Iterator iter = m_listeners.iterator(); iter.hasNext(); )
                      {
                          ValueProfilePointListener listener =
                              (ValueProfilePointListener)iter.next();
                          listener.setValue( getName(), value, time );
                      }
                  }
              }
          }
      }
      
      /**
       * Add a ProfileSample to the ProfilePoint.
       *
       * @param profileSample ProfileSample to be added.
       *
       * @throws ConfigurationException If there are any configuration problems
       *                                with the ProfileSample.
       */
      public void addProfileSample( ProfileSample profileSample )
          throws ConfigurationException
      {
          synchronized(this)
          {
              // If the type has not been set, set it.  If it has been set, make sure this sample has
              //  the same type.
              if ( m_type == ProfilerManager.PROFILE_POINT_TYPE_NONE )
              {
                  setType( profileSample.getProfilePointType() );
              }
              else if ( m_type != profileSample.getProfilePointType() )
              {
                  // The type is different.
                  throw new ConfigurationException( "The sample '" + profileSample.getName() + 
                      "' had its type set to " + getTypeName( m_type ) + 
                      " by another sample.  This sample has a type of " + 
                      getTypeName( profileSample.getProfilePointType() ) + " and is not compatible." );
              }
              
              // Make sure that a sample with the same name has not already been set.
              String sampleName = profileSample.getName();
              if ( m_samples.get( sampleName ) != null )
              {
                  throw new ConfigurationException( "More than one sample with the same name, '" +
                      sampleName + "', can not be configured." );
              }
          
              // Sample is safe to add.
              m_samples.put( sampleName, profileSample );
              
              // Clear the optimized arrays
              m_sampleArray = null;
              m_sampleDescriptorArray = null;
              
              // Add the sample as a listener for this ProfilePoint.
              switch ( m_type )
              {
              case ProfilerManager.PROFILE_POINT_TYPE_COUNTER:
                  addCounterProfilePointListener( (CounterProfileSample)profileSample );
                  break;
                  
              case ProfilerManager.PROFILE_POINT_TYPE_VALUE:
                  addValueProfilePointListener( (AbstractValueProfileSample)profileSample );
                  break;
                  
              default:
                  throw new IllegalStateException(
                      "Don't know how to deal with the type: " + m_type );
              }
          }
      }
      
      /**
       * Returns a ProfileSample based on its name.
       *
       * @param profileSampleName Name of the ProfileSample being requested.
       *
       * @return The requested ProfileSample or null if does not exist.
       */
      ProfileSample getProfileSample( String profileSampleName )
      {
          synchronized(this)
          {
              return (ProfileSample)m_samples.get( profileSampleName );
          }
      }
      
      /**
       * Returns an array of the ProfileSamples in the ProfilePoint.
       *
       * @return An array of the ProfileSamples in the ProfilePoint.
       */
      ProfileSample[] getProfileSamples()
      {
          ProfileSample[] samples = m_sampleArray;
          if ( samples == null )
          {
              samples = updateProfileSampleArray();
          }
          return samples;
      }
      
      /**
       * Returns an array of Descriptors for the ProfileSamples in the
       *  ProfilePoint.
       *
       * @return An array of Descriptors for the ProfileSamples in the
       *         ProfilePoint.
       */
      ProfileSampleDescriptor[] getProfileSampleDescriptors()
      {
          ProfileSampleDescriptor[] descriptors = m_sampleDescriptorArray;
          if ( descriptors == null )
          {
              descriptors = updateProfileSampleDescriptorArray();
          }
          return descriptors;
      }
      
      /**
       * Updates the cached array of ProfileSamples taking synchronization into
       *  account.
       *
       * @return An array of the ProfileSamples.
       */
      private ProfileSample[] updateProfileSampleArray()
      {
          synchronized(this)
          {
              m_sampleArray = new ProfileSample[ m_samples.size() ];
              m_samples.values().toArray( m_sampleArray );
              
              return m_sampleArray;
          }
      }
      
      /**
       * Updates the cached array of ProfileSampleDescriptors taking
       *  synchronization into account.
       *
       * @return An array of the ProfileSampleDescriptors.
       */
      private ProfileSampleDescriptor[] updateProfileSampleDescriptorArray()
      {
          synchronized(this)
          {
              if ( m_sampleArray == null )
              {
                  updateProfileSampleArray();
              }
              
              m_sampleDescriptorArray =
                  new ProfileSampleDescriptor[ m_sampleArray.length ];
              for ( int i = 0; i < m_sampleArray.length; i++ )
              {
                  m_sampleDescriptorArray[i] = m_sampleArray[i].getDescriptor();
              }
              
              return m_sampleDescriptorArray;
          }
      }
      
      /**
       * Returns the name of a ProfilePoint type.
       *
       * @param type Type whose name is wanted.
       *
       * @return The name of a ProfilePoint type.
       */
      public static String getTypeName( int type )
      {
          switch ( type )
          {
          case ProfilerManager.PROFILE_POINT_TYPE_NONE:
              return "none";
          case ProfilerManager.PROFILE_POINT_TYPE_COUNTER:
              return "counter";
          case ProfilerManager.PROFILE_POINT_TYPE_VALUE:
              return "value";
          default:
              throw new IllegalArgumentException( type + " is not a known ProfilePoint type." );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfileSample.java
  
  Index: ProfileSample.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.altprofile.profiler;
  
  import org.apache.avalon.framework.logger.LogEnabled;
  
  /**
   * The ProfileSample represents a single data sample in a ProfileDataSet.
   * Access to ProfileSamples are synchronized through the ProfileDataSet.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface ProfileSample
  	extends LogEnabled
  {
      /**
  	 * Returns the name of the sample.
  	 *
  	 * @return The name of the sample.
  	 */
      String getName();
      
      /**
  	 * Returns the sample interval.  The period of each sample in millisends.
  	 *
  	 * @return The sample interval.
  	 */
      long getInterval();
      
      /**
  	 * Returns the number of samples in the sample history.
  	 *
  	 * @return The size of the sample history.
  	 */
      int getSize();
      
      /**
  	 * Returns the description of the sample.
  	 *
  	 * @return The description of the sample.
  	 */
      String getDescription();
      
  	/**
  	 * Returns a Descriptor for the ProfileSample.
  	 *
  	 * @return A Descriptor for the ProfileSample.
  	 */
  	ProfileSampleDescriptor getDescriptor();
  	
  	/**
  	 * Obtain the value of the sample.  All samples are integers, so the profiled
  	 * objects must measure quantity (numbers of items), rate (items/period), time in
  	 * milliseconds, etc.
  	 *
  	 * @return The sample value.
  	 */
      int getValue();
      
      /**
  	 * Obtain the UNIX time of the beginning of the sample.
  	 *
  	 * @return The UNIX time of the beginning of the sample.
  	 */
      long getTime();
      
      /**
  	 * Returns the Type of the ProfilePoint which can use the sample.  This
  	 *  should be the same for all instances of a class.
  	 * <p>
  	 * Should be one of the following: ProfilerManager.PROFILE_POINT_TYPE_COUNTER
  	 *  or ProfilerManager.PROFILE_POINT_TYPE_VALUE
  	 *
  	 * @return The Type of the ProfilePoint which can use the sample.
  	 */
      int getProfilePointType();
      
      /**
  	 * Obtains a static snapshot of the ProfileSample.
  	 *
  	 * @return A static snapshot of the ProfileSample.
  	 */
      ProfileSampleSnapshot getSnapshot();
      
      /**
  	 * Registers a ProfileSampleListener with a ProfileSample given a name.
  	 *
  	 * @param listener The listener which should start receiving updates from the
  	 *                 ProfileSample.
  	 */
      void addProfileSampleListener( ProfileSampleListener listener );
      
      /**
  	 * Unregisters a ProfileSampleListener from a ProfileSample given a name.
  	 *
  	 * @param listener The listener which should stop receiving updates from the
  	 *                 ProfileSample.
  	 */
      void removeProfileSampleListener( ProfileSampleListener listener );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfileSampleDescriptor.java
  
  Index: ProfileSampleDescriptor.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.altprofile.profiler;
  
  /**
   * Describes a ProfileSample and acts as a Proxy to protect the original ProfileSample object.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfileSampleDescriptor
  {
      /** The ProfileSample. */
      private ProfileSample m_profileSample;
      
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new ProfileSampleDescriptor.
  	 *
  	 * @param profileSample ProfileSample being described.
  	 */
      ProfileSampleDescriptor( ProfileSample profileSample )
      {
          m_profileSample = profileSample;
      }
      
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      /**
  	 * Returns the name of the sample.
  	 *
  	 * @return The name of the sample.
  	 */
      public String getName()
      {
          return m_profileSample.getName();
      }
      
      /**
  	 * Returns the sample interval.  The period of each sample in millisends.
  	 *
  	 * @return The sample interval.
  	 */
      public long getInterval()
      {
          return m_profileSample.getInterval();
      }
      
      /**
  	 * Returns the number of samples in the sample history.
  	 *
  	 * @return The size of the sample history.
  	 */
      public int getSize()
      {
          return m_profileSample.getSize();
      }
      
      /**
  	 * Returns the description of the sample.
  	 *
  	 * @return The description of the sample.
  	 */
      public String getDescription()
      {
          return m_profileSample.getDescription();
      }
      
      /**
  	 * Obtain the value of the sample.  All samples are integers, so the profiled
  	 * objects must measure quantity (numbers of items), rate (items/period), time in
  	 * milliseconds, etc.
  	 *
  	 * @return The sample value.
  	 */
      public int getValue()
      {
          return m_profileSample.getValue();
      }
      
      /**
  	 * Obtain the UNIX time of the beginning of the sample.
  	 *
  	 * @return The UNIX time of the beginning of the sample.
  	 */
      public long getTime()
      {
          return m_profileSample.getTime();
      }
      
      /**
  	 * Returns the Type of the ProfilePoint which can use the sample.  This
  	 *  should be the same for all instances of a class.
  	 * <p>
  	 * Should be one of the following: ProfilerManager.PROFILE_POINT_TYPE_COUNTER
  	 *  or ProfilerManager.PROFILE_POINT_TYPE_VALUE
  	 *
  	 * @return The Type of the ProfilePoint which can use the sample.
  	 */
      public int getProfilePointType()
      {
          return m_profileSample.getProfilePointType();
      }
      
      /**
  	 * Obtains a static snapshot of the ProfileSample.
  	 *
  	 * @return A static snapshot of the ProfileSample.
  	 */
      public ProfileSampleSnapshot getSnapshot()
      {
          return m_profileSample.getSnapshot();
      }
  	
  	/**
  	 * Registers a ProfileSampleListener with a ProfileSample given a name.
  	 *
  	 * @param listener The listener which should start receiving updates from the
  	 *                 ProfileSample.
  	 */
  	public void addProfileSampleListener( ProfileSampleListener listener )
  	{
  		m_profileSample.addProfileSampleListener( listener );
  	}
  	
  	/**
  	 * Unregisters a ProfileSampleListener from a ProfileSample given a name.
  	 *
  	 * @param listener The listener which should stop receiving updates from the
  	 *                 ProfileSample.
  	 */
  	public void removeProfileSampleListener( ProfileSampleListener listener )
  	{
  		m_profileSample.removeProfileSampleListener( listener );
  	}
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfileSampleFactory.java
  
  Index: ProfileSampleFactory.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.altprofile.profiler;
  
  import org.apache.avalon.framework.configuration.ConfigurationException;
  
  /**
   * The ProfileSample represents a single data sample in a ProfileDataSet.
   * Access to ProfileSamples are synchronized through the ProfileDataSet.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  class ProfileSampleFactory
  {
      /**
       * A Profile Sample Type loaded in from a Configuration.
       *
       * @param type Type of the ProfileSample to create.  Accepted values are:
       *              "max", "maximum", "min", "minimum", "avg", "average", 
       *              "ctr", and "counter".
       * @param name The name of the new ProfileSample.
       * @param interval The sample interval of the new ProfileSample.
       * @param size The number of samples to store as history.
       * @param description The description of the new ProfileSample.
       */
      static ProfileSample getProfileSample( String type,
                                             String name,
                                             long interval,
                                             int size,
                                             String description )
          throws ConfigurationException
      {
          if ( type.equalsIgnoreCase( "max" ) || type.equalsIgnoreCase( "maximum" ) )
          {
              return new MaximumValueProfileSample( name, interval, size, description );
          }
          else if ( type.equalsIgnoreCase( "min" ) || type.equalsIgnoreCase( "minimum" ) )
          {
              return new MinimumValueProfileSample( name, interval, size, description );
          }
          else if ( type.equalsIgnoreCase( "avg" ) || type.equalsIgnoreCase( "average" ) )
          {
              return new AverageValueProfileSample( name, interval, size, description );
          }
          else if ( type.equalsIgnoreCase( "ctr" ) || type.equalsIgnoreCase( "counter" ) )
          {
              return new CounterProfileSample( name, interval, size, description );
          }
          else
          {
              throw new ConfigurationException( "'" + type + "' is not a valid sample type." );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfileSampleListener.java
  
  Index: ProfileSampleListener.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.altprofile.profiler;
  
  /**
   * Objects which implement the ProfileSampleListener interface can register
   *  themselves with ProfileSample instances to receive updates on their value.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface ProfileSampleListener
  {
      /**
       * Called by a ProfileSample whenever its value is changed.
       *
       * @param profileSampleName The name of the ProfileSample whose value was changed.
       * @param value The new value.
       * @param time The time that the ProfileSample value was changed.
       */
      void setValue( String profileSampleName, int value, long time );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfileSampleSnapshot.java
  
  Index: ProfileSampleSnapshot.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.altprofile.profiler;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public class ProfileSampleSnapshot
  {
      /** The name used to reference the ProfileSample. */
      private String m_profileSampleName;
      
      /** The interval between each sample. */
      private long m_interval;
      
      /** The number of samples in the ProfileSample. */
      private int m_size;
      
      /** The time that the last sample starts. */
      private long m_time;
      
      /** The samples as an array of integers. */
      private int[] m_samples;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * @param profileSampleName The name used to reference the ProfileSample.
       * @param interval The interval between each sample.
       * @param size The number of samples in the ProfileSample.
       * @param time The time that the last sample starts.
       * @param samples The samples as an array of integers.
       */
      ProfileSampleSnapshot( String profileSampleName,
                             long interval,
                             int size,
                             long time,
                             int[] samples )
      {
          m_profileSampleName = profileSampleName;
          m_interval = interval;
          m_size = size;
          m_time = time;
          m_samples = samples;
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Returns the name used to reference the ProfileSample.
       *
       * @return The name used to reference the ProfileSample.
       */
      public String getProfileSampleName()
      {
          return m_profileSampleName;
      }
      
      /**
       * Returns the interval, in milliseconds, between each sample.
       *
       * @return The interval between each sample.
       */
      public long getInterval()
      {
          return m_interval;
      }
      
      /**
       * Returns the number of samples in the ProfileSample.
       *
       * @return The number of samples in the ProfileSample.
       */
      public int getSize()
      {
          return m_size;
      }
      
      /**
       * Returns the time that the last sample starts.
       *
       * @return The time that the last sample starts.
       */
      public long getTime()
      {
          return m_time;
      }
      
      /**
       * Returns the samples as an array of integers.  The sample at index 0
       *  will be the oldest.  The end of the array is the newest.
       *
       * @return The samples as an array of integers.
       */
      public int[] getSamples()
      {
          return m_samples;
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfilerManageable.java
  
  Index: ProfilerManageable.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.altprofile.profiler;
  
  /**
   * ProfilerManageable Interface, use this to set the ProfilerManagers for child
   * Components.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.0
   */
  public interface ProfilerManageable
  {
      /**
       * Sets the ProfilerManager for child components.  Can be for special
       * purpose components, however it is used mostly internally.
       *
       * @param profilerManager The ProfilerManager for the component to use.
       */
      void setProfilerManager( final ProfilerManager profilerManager );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ProfilerManager.java
  
  Index: ProfilerManager.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.altprofile.profiler;
  
  import org.apache.avalon.excalibur.altprofile.Profilable;
  
  import org.apache.avalon.framework.configuration.Configuration;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface ProfilerManager
  {
      /** Type which specifies that the type of a ProfilePoint has not yet been determined. */
      int PROFILE_POINT_TYPE_NONE = 0;
      
      /** Type which identifies CounterProfilePoints. */
      int PROFILE_POINT_TYPE_COUNTER = 1;
      
      /** Type which identifies ValueProfilePoints. */
      int PROFILE_POINT_TYPE_VALUE   = 2;
      
  	/**
  	 * Returns a ProfilableDescriptor based on its name.
  	 *
  	 * @param profilableName Name of the Profilable being requested.
  	 *
  	 * @return A Descriptor of the requested Profilable.
  	 *
  	 * @throws NoSuchProfilableException If the specified Profilable does
  	 *                                   not exist.
  	 */
  	ProfilableDescriptor getProfilableDescriptor( String profilePointName )
  		throws NoSuchProfilableException;
  		
  	/**
  	 * Returns an array of Descriptors for the Profilables managed by this
  	 *  ProfilerManager.
  	 *
  	 * @return An array of Descriptors for the Profilables managed by this
  	 *  ProfilerManager.
  	 */
  	ProfilableDescriptor[] getProfilableDescriptors();
      
      /**
  	 * Profilable to be registered with the profile manager.  Should be called
  	 *  happen whenever a Profilable is created.
  	 *
  	 * @param profilable Profilable to register with the ProfilerManager.
  	 * @param configuration The configuration of the Profilable.
  	 *
  	 * @throws Exception if there was a problem registering the Profilable.
  	 */
      void registerProfilable( Profilable profilable, Configuration configuration ) throws Exception;
      
      /**
  	 * Profilable to be unregistered from the profile manager.  Should be
  	 *  called whenever a Profilable is disposed.
  	 *
  	 * @param profilable Profilable to unregister from the ProfilerManager.
  	 */
      //void unregisterProfilable( Profilable profilable );
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/ValueProfilePointListener.java
  
  Index: ValueProfilePointListener.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.altprofile.profiler;
  
  /**
   * Objects which implement the ProfilePointListener interface can register
   *  themselves with ProfilePoint instances to receive updates on the
   *  Profile Point's value.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:43 $
   * @since 4.1
   */
  public interface ValueProfilePointListener
  {
      /**
       * Called by a ValueProfilePoint whenever its value is set.
       *
       * @param profilePointKey The key of ProfilePoint whose value was set.
       * @param value Value that was set.
       * @param time The time that the ProfilePoint was incremented.
       *
       * ValueProfilePoint
       */
      void setValue( String profilePointKey, int value, long time );
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui/AbstractInternalFrame.java
  
  Index: AbstractInternalFrame.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.altprofile.profiler.gui;
  
  import java.awt.BorderLayout;
  import java.awt.Dimension;
  
  import javax.swing.JDesktopPane;
  import javax.swing.JInternalFrame;
  import javax.swing.JPanel;
  import javax.swing.event.InternalFrameEvent;
  import javax.swing.event.InternalFrameListener;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:44 $
   * @since 4.1
   */
  abstract class AbstractInternalFrame
      extends JInternalFrame
      implements InternalFrameListener
  {
      private ProfilerFrame m_profilerFrame;
      private JInternalFrame m_nextFrame;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      AbstractInternalFrame( String title, 
                             boolean resizable,
                             boolean closable,
                             boolean maximizable,
                             boolean iconifiable,
                             ProfilerFrame profilerFrame )
      {
          super( title, resizable, closable, maximizable, iconifiable );
          
          m_profilerFrame = profilerFrame;
          
          // Set the content pane so that it is the right color
          JPanel contentPane = new JPanel();
          contentPane.setLayout( new BorderLayout() );
          setContentPane( contentPane );
          
          addInternalFrameListener( this );
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Adds the frame to the desktop in a simple and dumb cascading format.
       */
      void addToDesktop( JDesktopPane desktop )
      {
          // Make sure that the size is valid
          Dimension maxSize = desktop.getSize();
          Dimension size = getSize();
          if ( ( maxSize.width < size.width ) || ( maxSize.height < size.height ) )
          {
              setSize( new Dimension( Math.min( maxSize.width, size.width ),
                  Math.min( maxSize.height, size.height ) ) );
              size = getSize();
          }
  
          // Position the frame
          int max = (int)Math.min( Math.ceil( ( maxSize.width - size.width ) / 20.0 ),
              Math.ceil( ( maxSize.height - size.height ) / 20.0 ) );
          
          JInternalFrame[] frames = desktop.getAllFrames();
          int pos;
          if (max > 0) {
              pos = ( frames.length % max ) * 20;
          } else {
              pos = 0;
          }
          setLocation( pos, pos );
          
          desktop.add( this );
      }
      
      void hideFrame()
      {
          setVisible( false );
          dispose();
      }
      
      public void updateUI()
      {
          super.updateUI();
          
          pack();
          setMinimumSize( getSize() );
      }
      
      /*---------------------------------------------------------------
       * InternalFrameListener Methods
       *-------------------------------------------------------------*/
      public void internalFrameOpened( InternalFrameEvent event ) {}
      public void internalFrameClosing( InternalFrameEvent event )
      {
          // Select the new top frame
          JDesktopPane desktop = m_profilerFrame.getDesktopPane();
          JInternalFrame[] frames = desktop.getAllFrames();
          // Find the first frame other than the one being hidden and select and move it to the front
          m_nextFrame = null;
          for ( int i = 0; i < frames.length; i++ )
          {
              JInternalFrame frame = frames[i];
              if ( frame != this )
              {
                  m_nextFrame = frame;
                  
                  // Break out
                  i = frames.length;
              }
          }
      }
      
      public void internalFrameClosed( InternalFrameEvent event )
      {
          // On closing Swing will bring forward the window at the bottom,
          //	rather than the next window.  So we need to move it back and show the correct one.		
          if ( m_nextFrame != null )
          {
              // The getSelectedFrame method was added in JDK1.3, so it may not yet exist.
              // Cast this to our workaround DesktopPane to work around this.
              DesktopPane desktop = (DesktopPane)m_profilerFrame.getDesktopPane();
              JInternalFrame top = desktop.getSelectedFrame();
              
              if ( top != null )
              {
                  if ( top != m_nextFrame )
                  {
                      try
                      {
                          m_nextFrame.setSelected( true );
                          desktop.moveToFront( m_nextFrame );
                          desktop.moveToBack( top );
                      }
                      catch ( java.beans.PropertyVetoException e ) {}
                  }
              }
          }
      }
      public void internalFrameIconified( InternalFrameEvent event ) {}
      public void internalFrameDeiconified( InternalFrameEvent event )
      {
          // Swing always activates a frame when it is deiconified, but it down't
          //  always move it to the front
          JDesktopPane desktop = m_profilerFrame.getDesktopPane();
          desktop.moveToFront( this );
      }
      public void internalFrameActivated( InternalFrameEvent event ) {}
      public void internalFrameDeactivated(InternalFrameEvent event) {}
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui/DesktopPane.java
  
  Index: DesktopPane.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.altprofile.profiler.gui;
  
  import javax.swing.JDesktopPane;
  import javax.swing.JInternalFrame;
  
  /**
   * This class was build to make it possible to use some of the JDK1.3
   *  features work in 1.2.2. Taken from JDK1.3 source to make it work.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:44 $
   * @since 4.1
   */
  class DesktopPane extends JDesktopPane
  {
      private transient JInternalFrame selectedFrame = null;
      
      /**
       * Used to indicate you wish to see the entire contents of the item being
       * dragged inside the desktop pane.
       *
       * @see #OUTLINE_DRAG_MODE
       * @see #setDragMode
       */
      public static int LIVE_DRAG_MODE = 0;
      
      /**
       * Used to indicate you wish to see only an outline of the item being
       * dragged inside the desktop pane.
       *
       * @see #LIVE_DRAG_MODE
       * @see #setDragMode
       */
      public static int OUTLINE_DRAG_MODE = 1;
      
      private int dragMode = LIVE_DRAG_MODE;
      
      /** 
       * Set the "dragging style" used by the desktop pane.  You may want to change
       * to one mode or another for performance or aesthetic reasons.
       *
       * @param dragMode the style of drag to use for items in the Desktop 
       *
       * @beaninfo
       *        bound: true
       *  description: Dragging style for internal frame children.
       *         enum: LIVE_DRAG_MODE JDesktopPane.LIVE_DRAG_MODE
       *               OUTLINE_DRAG_MODE JDesktopPane.OUTLINE_DRAG_MODE
       */
      public void setDragMode( int dragMode )
      {
          /* if (!(dragMode == LIVE_DRAG_MODE || dragMode == OUTLINE_DRAG_MODE)) {
          throw new IllegalArgumentException("Not a valid drag mode");
          }*/
          firePropertyChange( "dragMode", this.dragMode, dragMode );
          this.dragMode = dragMode;
      }
      
      /** 
       * Get the current "dragging style" used by the desktop pane.
       * @see #setDragMode
       */
      public int getDragMode()
      {
          return dragMode;
      }
      
      /** return the currently active JInternalFrame in this JDesktopPane, or
       * null if no JInternalFrame is currently active.
       *
       * @return the currently active JInternalFrame or null
       * @since 1.3
       */
      public JInternalFrame getSelectedFrame()
      {
          return selectedFrame;
      }
      
      /** set the currently active JInternalFrame in this JDesktopPane.
       *
       * @param f The internal frame that's currently selected
       * @since 1.3
       */
      
      public void setSelectedFrame( JInternalFrame f )
      {
          selectedFrame = f;
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui/LineChart.java
  
  Index: LineChart.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.altprofile.profiler.gui;
  
  import java.awt.Color;
  import java.awt.Dimension;
  import java.awt.FontMetrics;
  import java.awt.Graphics;
  import java.awt.Insets;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
  import java.awt.event.MouseMotionListener;
  import java.text.MessageFormat;
  import java.util.Calendar;
  import java.util.Date;
  import javax.swing.JComponent;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:44 $
   * @since 4.1
   */
  public class LineChart
      extends JComponent
      implements MouseListener, MouseMotionListener
  {
      private static final long _baseTime;
      private Color _lineColor = Color.red;
      private Color _lightLineColor = new Color(255, 128, 128);
      private Color _lightGridColor = new Color(192, 192, 192);
      private Color _darkGridColor = new Color(128, 128, 128);
      private Color _frameColor = Color.black;
      private Color _crossColor = Color.blue;
      private Color _maskFrameColor = new Color(128, 128, 255, 192);
      private Color _maskColor = new Color(224, 224, 255, 192);
      private int _hInt;
      private int _tickSecs;
      private String _format;
      private String _dFormat;
      private int _average;
      private int _min;
      private int _max;
      private int[] _values;
      private float[] _aValues;
      private boolean _mouseOver;
      private boolean _mousePressed;
      private int _mouseX;
      private int _mouseY;
      
      static {
          // Set the base time to the beginning of this year in seconds
          Calendar calendar = Calendar.getInstance();
          int year = calendar.get(Calendar.YEAR);
          calendar.clear();
          calendar.set(Calendar.YEAR, year);
          _baseTime = calendar.getTime().getTime() / 1000;
      }
      
      /*---------------------------------------------------------------
       * Constructor
       *-------------------------------------------------------------*/
      /**
       * Creates a new LineChart.
       *
       *
       */
      public LineChart(int horizontalInterval, int tickSeconds, String format, String detailFormat) {
          this(horizontalInterval, tickSeconds, format, detailFormat, 0);
      }
      
      /**
       * @param horizontalInterval The interval in data points at which to place vertical
       *	lines and labels along the x (time) axis.
       * @param tickSeconds The number of seconds represented by each data point.
       * @param format Format of the text which is displayed along the x (time) axis of
       *	the chart.  The text will display the time of the line chart at a particular
       *	interval.  The text should take the format "{0}/{1} {2}:{3}:{4}" where {0} is
       *	replaced by the month, {1} by the day, {2} by the hour, {3} by the minute and {4}
       *	by the second.
       * @param detailFormat Format of the text which is displayed over the component as
       *	the user moves the mouse over the line chart.  The text will display the exact
       *	value of the line chart at a particular point.  The text should take the format
       *	"{0}/{1} {2}:{3}:{4}" where {0} is replaced by the month, {1} by the day, {2} by the
       *	hour, {3} by the minute and {4} by the second.
       * @param averageWindow Number of data points to do a moving average over when the
       *	mouse is pressed on the component.
       */
      LineChart(int horizontalInterval, int tickSeconds, String format, String detailFormat, int averageWindow) {
          _hInt = horizontalInterval;
          _tickSecs = tickSeconds;
          _format = format;
          _dFormat = detailFormat;
          _average = averageWindow;
          
          setBackground(Color.white);
          setValues(new int[0]);
          addMouseListener(this);
          addMouseMotionListener(this);
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      synchronized void setValues(int[] values) {
          int max = 0;
          int min = Integer.MAX_VALUE;
          for (int i = 0; i < values.length; i++) {
              int v = values[i];
              if (v > max) max = v;
              if (v < min) min = v;
          }
          if ((max - min) < 10) {
              max += ((10 - (max - min)) / 2);
              min -= (10 - (max - min));
          }
          if (min < 0) {
              max += -min;
              min = 0;
          }
      
          float[] aValues = new float[values.length];
          if (_average > 1) {
              int total = 0;
              for (int i = 0; i < values.length; i++) {
                  total += values[i];
                  if (i >= _average - 1) {
                      if (i >= _average) {
                          total -= values[i - _average];
                      }
                      aValues[i] = (float)total / _average;
                  } else {
                      aValues[i] = Float.MIN_VALUE;
                  }
              }
          }
          
          synchronized(this) {		
              _values = values;
              _aValues = aValues;
              _min = min;
              _max = max;
          }
          repaint();
      }
      
      private String getFormattedTime(Date dTime, boolean detailed) {
          Calendar calendar = Calendar.getInstance();
          calendar.setTime(dTime);
          
          int v;
          String month, day, hour, minute, second;
          
          // Substitute the month
          v = calendar.get(Calendar.MONTH) - Calendar.JANUARY + 1;
          if (v < 10) {
              month = "0" + Integer.toString(v);
          } else {
              month = Integer.toString(v);
          }
          
          // Substiture the Day
          v = calendar.get(Calendar.DAY_OF_MONTH);
          if (v < 10) {
              day = "0" + Integer.toString(v);
          } else {
              day = Integer.toString(v);
          }
  
          // Substiture the Hour
          v = calendar.get(Calendar.HOUR_OF_DAY);
          if (v < 10) {
              hour = "0" + Integer.toString(v);
          } else {
              hour = Integer.toString(v);
          }
  
          // Substiture the Minute
          v = calendar.get(Calendar.MINUTE);
          if (v < 10) {
              minute = "0" + Integer.toString(v);
          } else {
              minute = Integer.toString(v);
          }
          
          // Substiture the Second
          v = calendar.get(Calendar.SECOND);
          if (v < 10) {
              second = "0" + Integer.toString(v);
          } else {
              second = Integer.toString(v);
          }
          
          String format;
          if (detailed) {
              format = MessageFormat.format(_dFormat, new Object[] {month, day, hour, minute, second});
          } else {
              format = MessageFormat.format(_format, new Object[] {month, day, hour, minute, second});
          }
          return format;
      }
      
      public synchronized void paintComponent(Graphics g) {
          Dimension size = getSize();
          Insets insets = getInsets();
          
          // Figure out the time at the beginning of the day
          long now = System.currentTimeMillis() / 1000;
          now = now - ((now - _baseTime) % _tickSecs);
          
          g.setColor(getBackground());
          g.fillRect(insets.left, insets.top, size.width - insets.left - insets.right, size.height - insets.top - insets.bottom);
          
          // Resolve the vertical interval
          int vInt = 1;
          while ((_max - _min) / vInt > 20) {
              vInt *= 10;
          }
          
          FontMetrics fm = g.getFontMetrics();
          int hlw = fm.stringWidth(Integer.toString(_max));
          int fh = fm.getAscent();
          int hh = fh / 2;
              
          int l = insets.left + hlw + 5;
          int t = insets.top + 5;
          int w = size.width - l - insets.right - 1 - 5;
          int h = size.height - t - insets.bottom - 1 - fh;
  
          // Draw the vertical grid
          int lInt = (int)Math.ceil((float)fh / (vInt * h / (_max - _min)));
          int lNum = 0;
          for (int i = ((int)Math.ceil((float)_min / vInt)) * vInt; i < _max; i += vInt) {
              int y = t + h - (h * (i - _min) / (_max - _min));
              
              if (lNum >= lInt) lNum = 0;
              if (lNum == 0) {
                  String lbl = Integer.toString(i);
                  g.setColor(_frameColor);
                  g.drawString(lbl, l - 5 - fm.stringWidth(lbl), y + hh);
  
                  g.setColor(_darkGridColor);
              } else {
                  g.setColor(_lightGridColor);
              }
              lNum++;
              
              g.drawLine(l, y, l + w, y);
          }
  
          // Draw the horizontal grid
          String format = MessageFormat.format(_format, new String[] {"00", "00","00", "00"});
          int fw = fm.stringWidth(format) + 10;
          
          if ((_values.length > 0) && (w > 0)) {
              lInt = (int)Math.ceil((float)fw / (_hInt * w / (_values.length)));
          } else {
              lInt = 1;
          }
          lNum = 0;
          for (int i = 0; i < _values.length; i++) {
              long time = now - (_values.length - i - 1) * _tickSecs;
              if ((((time - _baseTime) / _tickSecs) % _hInt) == 0) {
                  int x = l + i * w / (_values.length - 1);
                  
                  if ((lNum >= lInt) || (lNum == 0)) {
                      format = getFormattedTime(new Date(time * 1000), false);
                      
                      if (x - fm.stringWidth(format) / 2 >= l) {
                          g.setColor(_frameColor);
                          g.drawString(format, x - fm.stringWidth(format) / 2, t + h + fh);
                  
                          g.setColor(_darkGridColor);
                          lNum = 1;
                      } else {
                          g.setColor(_lightGridColor);
                      }
                  } else {
                      g.setColor(_lightGridColor);
                      lNum++;
                  }
                  
                  // Draw the vertical line
                  g.drawLine(x, t, x, t + h);
              }
          }
          
          // Draw the frame
          g.setColor(_frameColor);
          g.drawLine(l, t, l, t + h);
          g.drawLine(l, t + h, l + w, t + h);
          
          // Draw the counts
          if ((_average > 0) && (_mousePressed)) {
              g.setColor(_lightLineColor);
          } else {
              g.setColor(_lineColor);
          }
          
          int lx = 0;
          int ly = 0;
          for (int i = 0; i < _values.length; i++) {
              int x = l + i * w / (_values.length - 1);
              int y = t + h - (h * (_values[i] - _min) / (_max - _min));
              
              if (i > 0) {
                  g.drawLine(lx, ly, x, y);
              }
              
              lx = x;
              ly = y;
          }
          
          // Draw the average chart
          if ((_average > 0) && (_mousePressed)) {
              g.setColor(_lineColor);
              lx = 0;
              ly = 0;
              for (int i = _average; i < _aValues.length; i++) {
                  int x = l + i * w / (_aValues.length - 1);
                  int y = t + h - (int)(h * (_aValues[i] - _min) / (_max - _min));
                  
                  if (i > _average) {
                      g.drawLine(lx, ly, x, y);
                  }
                  
                  lx = x;
                  ly = y;
              }
          }
          
          // Make the label visible if the user tracks over any part of the chart rather than just on the cart area.
          //if ((_mouseOver) && (_mouseX >= l) && (_mouseX <= l + w) && (_mouseY >= t) && (_mouseY <= t + h)) {
          if ((_mouseOver) && (_mouseX >= l) && (_mouseX <= l + w)) {
              // Figure out where the mouse is
              int index = (int)Math.round((float)(_values.length - 1) * (_mouseX - l) / w);
              if ((_average > 0) && (_mousePressed)) {
                  // Draw the label for the average data
                  if ((index >= _average) && (index < _aValues.length)) {
                      int mx = l + index * w / (_aValues.length - 1);
                      int my = t + h - (int)(h * (_aValues[index] - _min) / (_max - _min));
                      float mc = (float)((int)(_aValues[index] * 100)) / 100;
                      long mt = now - (_aValues.length - index - 1) * _tickSecs;
                      
                      g.setColor(_crossColor);
                      g.drawLine(mx, t, mx, t + h);
                      g.drawLine(l, my, l + w, my);
                      format = mc + " : " + getFormattedTime(new Date(mt * 1000), true);
                      int tw = fm.stringWidth(format);
                      int ll, lt;
                      // Decide where to put the label
                      if (mx + 5 + tw < l + w) {
                          // Ok on the right
                          ll = mx + 4;
                          if (my + 5 + fh < t + h) {
                              // Ok on the bottom
                              lt = my + 4;
                          } else {
                              // Must go on the top
                              lt = my - 4 - fh;
                          }
                      } else {
                          // Must go on the left
                          ll = mx - 4 - tw;
                          if (my + 5 + fh < t + h) {
                              // Ok on the bottom
                              lt = my + 4;
                          } else {
                              // Must go on the top
                              lt = my - 4 - fh;
                          }
                      }
                      // Paint the label
                      g.setColor(_maskFrameColor);
                      g.drawRect(ll - 1, lt - 1, tw + 2, fh + 2);
                      g.setColor(_maskColor);
                      g.fillRect(ll - 1, lt - 1, tw + 2, fh + 2);
                      g.setColor(_crossColor);
                      g.drawString(format, ll, lt + fh);
                  }
              } else {
                  // Draw the label for the regular data
                  if ((index >= 0) && (index < _values.length)) {
                      int mx = l + index * w / (_values.length - 1);
                      int my = t + h - (h * (_values[index] - _min) / (_max - _min));
                      int mc = _values[index];
                      long mt = now - (_values.length - index - 1) * _tickSecs;
                      
                      g.setColor(_crossColor);
                      g.drawLine(mx, t, mx, t + h);
                      g.drawLine(l, my, l + w, my);
                      format = mc + " : " + getFormattedTime(new Date(mt * 1000), true);
                      int tw = fm.stringWidth(format);
                      int ll, lt;
                      // Decide where to put the label
                      if (mx + 5 + tw < l + w) {
                          // Ok on the right
                          ll = mx + 4;
                          if (my + 5 + fh < t + h) {
                              // Ok on the bottom
                              lt = my + 4;
                          } else {
                              // Must go on the top
                              lt = my - 4 - fh;
                          }
                      } else {
                          // Must go on the left
                          ll = mx - 4 - tw;
                          if (my + 5 + fh < t + h) {
                              // Ok on the bottom
                              lt = my + 4;
                          } else {
                              // Must go on the top
                              lt = my - 4 - fh;
                          }
                      }
                      // Paint the label
                      g.setColor(_maskFrameColor);
                      g.drawRect(ll - 1, lt - 1, tw + 2, fh + 2);
                      g.setColor(_maskColor);
                      g.fillRect(ll - 1, lt - 1, tw + 2, fh + 2);
                      g.setColor(_crossColor);
                      g.drawString(format, ll, lt + fh);
                  }
              }
          }
      }
      
      /*---------------------------------------------------------------
       * MouseListener Methods
       *-------------------------------------------------------------*/
      public void mouseClicked(MouseEvent event) {
      }
      
      public void mousePressed(MouseEvent event) {
          _mousePressed = true;
      }
      
      public void mouseReleased(MouseEvent event) {
          _mousePressed = false;
      }
      
      public void mouseEntered(MouseEvent event) {
          _mouseOver = true;
          repaint();
      }
      
      public void mouseExited(MouseEvent event) {
          _mouseOver = false;
          repaint();
      }
      
      /*---------------------------------------------------------------
       * MouseMotionListener Methods
       *-------------------------------------------------------------*/
      public void mouseDragged(MouseEvent event) {
          _mouseX = event.getX();
          _mouseY = event.getY();
          repaint();
      }
      
      public void mouseMoved(MouseEvent event) {
          _mouseX = event.getX();
          _mouseY = event.getY();
          repaint();
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui/MenuBar.java
  
  Index: MenuBar.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.altprofile.profiler.gui;
  
  import java.awt.event.ActionEvent;
  import java.util.Arrays;
  import java.util.Comparator;
  
  import javax.swing.AbstractAction;
  import javax.swing.Action;
  import javax.swing.JCheckBoxMenuItem;
  import javax.swing.JInternalFrame;
  import javax.swing.JMenu;
  import javax.swing.JMenuBar;
  import javax.swing.JMenuItem;
  import javax.swing.event.MenuEvent;
  import javax.swing.event.MenuListener;
  
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilableDescriptor;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilePointDescriptor;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfileSampleDescriptor;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:44 $
   * @since 4.1
   */
  public class MenuBar
      extends JMenuBar
  {
      private ProfilerFrame m_frame;
      private ProfilerManager m_profilerManager;
      
      private JMenu m_menuProfilables;
      
      private JMenu m_menuOptions;
      private JCheckBoxMenuItem m_menuItemShowUnconfigured;
      
      private JMenu m_menuWindow;
      
      private boolean m_showUnconfigured;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      MenuBar( ProfilerFrame frame, ProfilerManager profilerManager )
      {
          m_frame = frame;
          m_profilerManager = profilerManager;
          
          add( buildProfilablesMenu() );
          add( buildOptionsMenu() );
          add( buildWindowMenu() );
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      private JMenu buildProfilablesMenu()
      {
          m_menuProfilables = new JMenu( "Profilables" );
          m_menuProfilables.setMnemonic( 'P' );
          
          m_menuProfilables.addMenuListener( new MenuListener()
              {
                  public void menuSelected( MenuEvent event )
                  {
                      rebuildProfilablesMenu();
                  }
                  public void menuDeselected( MenuEvent event ) {}
                  public void menuCanceled( MenuEvent event ) {}
              } );
          
          return m_menuProfilables;
      }
      
      private void rebuildProfilablesMenu()
      {
          m_menuProfilables.removeAll();
          
          boolean showAll = m_menuItemShowUnconfigured.getState();
          
          ProfilableDescriptor[] profilableDescriptors = m_profilerManager.getProfilableDescriptors();
          
          Comparator comp = new Comparator()
          {
              public int compare( Object o1, Object o2 )
              {
                  return ((ProfilableDescriptor)o1).getDescription().
                      compareTo( ((ProfilableDescriptor)o2).getDescription() );
              }
              public boolean equals(Object obj)
              {
                  return false;
              }
          };
          Arrays.sort( profilableDescriptors, comp );
          
          for ( int i = 0; i < profilableDescriptors.length; i++ )
          {
              ProfilableDescriptor profilableDescriptor = profilableDescriptors[i];
              
              if ( showAll || profilableDescriptor.isConfigured() )
              {
                  String profilableName = profilableDescriptor.getDescription();
                  
                  Action action = new AbstractAction( profilableName )
                  {
                      public void actionPerformed( ActionEvent e ) {}
                  };
                  action.putValue( "profilableDescriptor", profilableDescriptor );
                  
                  JMenu menu = new JMenu( action );
                  
                  // Set up a Listener to handle the selected event.
                  menu.addMenuListener( new MenuListener()
                      {
                          public void menuSelected( MenuEvent event )
                          {
                              JMenu menu = (JMenu)event.getSource();
                              Action action = menu.getAction();
                              
                              rebuildProfilableMenu( menu,
                                  (ProfilableDescriptor)action.getValue( "profilableDescriptor" ) );
                          }
                          public void menuDeselected( MenuEvent event ) {}
                          public void menuCanceled( MenuEvent event ) {}
                      } );
                  
                  m_menuProfilables.add( menu );
              }
          }
      }
      
      private void rebuildProfilableMenu( JMenu profilableMenu,
                                          ProfilableDescriptor profilableDescriptor )
      {
          profilableMenu.removeAll();
          
          boolean showAll = m_menuItemShowUnconfigured.getState();
          
          ProfilePointDescriptor[] profilePointDescriptors =
              profilableDescriptor.getProfilePointDescriptors();
          
          Comparator comp = new Comparator()
          {
              public int compare( Object o1, Object o2 )
              {
                  return ((ProfilePointDescriptor)o1).getDescription().
                      compareTo( ((ProfilePointDescriptor)o2).getDescription() );
              }
              public boolean equals(Object obj)
              {
                  return false;
              }
          };
          Arrays.sort( profilePointDescriptors, comp );
          
          for ( int i = 0; i < profilePointDescriptors.length; i++ )
          {
              ProfilePointDescriptor profilePointDescriptor = profilePointDescriptors[i];
              
              if ( showAll || profilePointDescriptor.isConfigured() )
              {
                  // Do not show typeless profilePoints
                  if ( profilePointDescriptor.getType() != ProfilerManager.PROFILE_POINT_TYPE_NONE )
                  {
                   String profilePointName = profilePointDescriptor.getDescription();
                  
                      Action action = new AbstractAction( profilePointName )
                      {
                          public void actionPerformed( ActionEvent e ) {}
                      };
                      action.putValue( "profilableDescriptor", profilableDescriptor );
                      action.putValue( "profilePointDescriptor", profilePointDescriptor );
                      
                      JMenu menu = new JMenu( action );
                      
                      // Set up a Listener to handle the selected event.
                      menu.addMenuListener( new MenuListener()
                          {
                              public void menuSelected( MenuEvent event )
                              {
                                  JMenu menu = (JMenu)event.getSource();
                                  Action action = menu.getAction();
                                  
                                  rebuildProfilePointMenu( menu,
                                      (ProfilableDescriptor)action.getValue( "profilableDescriptor" ),
                                      (ProfilePointDescriptor)action.
                                      getValue( "profilePointDescriptor" ) );
                              }
                              public void menuDeselected( MenuEvent event ) {}
                              public void menuCanceled( MenuEvent event ) {}
                          } );
                      
                      profilableMenu.add( menu );
                  }
              }
          }
      }
      
      private void rebuildProfilePointMenu( JMenu profilePointMenu,
                                            ProfilableDescriptor profilableDescriptor,
                                            ProfilePointDescriptor profilePointDescriptor )
      {
          profilePointMenu.removeAll();
          
          ProfileSampleDescriptor[] profileSampleDescriptors = profilePointDescriptor.getProfileSampleDescriptors();
          
          Comparator comp = new Comparator()
          {
              public int compare( Object o1, Object o2 )
              {
                  return ((ProfileSampleDescriptor)o1).getDescription().
                      compareTo( ((ProfileSampleDescriptor)o2).getDescription() );
              }
              public boolean equals(Object obj)
              {
                  return false;
              }
          };
          Arrays.sort( profileSampleDescriptors, comp );
          
          for ( int i = 0; i < profileSampleDescriptors.length; i++ )
          {
              ProfileSampleDescriptor profileSampleDescriptor = profileSampleDescriptors[i];
              
              String profileSampleName = profileSampleDescriptor.getDescription();
              
              Action action = new AbstractAction( profileSampleName )
              {
                  public void actionPerformed( ActionEvent event )
                  {
                      JMenuItem menu = (JMenuItem)event.getSource();
                      Action action = menu.getAction();
                      
                      m_frame.openProfileSampleFrame(
                          (ProfilableDescriptor)action.getValue( "profilableDescriptor" ),
                          (ProfilePointDescriptor)action.getValue( "profilePointDescriptor" ),
                          (ProfileSampleDescriptor)action.getValue( "profileSampleDescriptor" ) );
                  }
              };
              action.putValue( "profilableDescriptor", profilableDescriptor );
              action.putValue( "profilePointDescriptor", profilePointDescriptor );
              action.putValue( "profileSampleDescriptor", profileSampleDescriptor );
              
              JMenuItem item = new JMenuItem( action );
              
              profilePointMenu.add( item );
          }
      }
      
      private JMenu buildOptionsMenu()
      {
          m_menuOptions = new JMenu( "Options" );
          m_menuOptions.setMnemonic( 'O' );
          
          // Show Unconfigured Profilables option
          m_menuItemShowUnconfigured =
              new JCheckBoxMenuItem( "Show Unconfigured Profilables", false );
          m_menuOptions.add( m_menuItemShowUnconfigured );
          
          return m_menuOptions;
      }
      
      private JMenu buildWindowMenu()
      {
          m_menuWindow = new JMenu( "Window" );
          m_menuWindow.setMnemonic( 'W' );
          
          m_menuWindow.addMenuListener( new MenuListener()
              {
                  public void menuSelected( MenuEvent event )
                  {
                      rebuildWindowMenu();
                  }
                  public void menuDeselected( MenuEvent event ) {}
                  public void menuCanceled( MenuEvent event ) {}
              } );
          
          return m_menuWindow;
      }
      
      private void rebuildWindowMenu()
      {
          m_menuWindow.removeAll();
          
          JInternalFrame[] frames = m_frame.getDesktopPane().getAllFrames();
          for ( int i = 0; i < frames.length; i++ )
          {
              String label = ( i + 1 ) + " " + frames[i].getTitle();
              Action action = new AbstractAction( label )
              {
                  public void actionPerformed( ActionEvent event )
                  {
                      JMenuItem menu = (JMenuItem)event.getSource();
                      Action action = menu.getAction();
                      
                      JInternalFrame frame = (JInternalFrame)action.getValue( "frame" );
                      try
                      {
                          if ( frame.isIcon() )
                          {
                              // Restore the frame
                              frame.setIcon( false );
                          }
                          frame.setSelected( true );
                          m_frame.getDesktopPane().moveToFront( frame );
                      }
                      catch (java.beans.PropertyVetoException e) {}
                  }
              };
              action.putValue( "frame", frames[i] );
              
              JMenuItem item = new JMenuItem( action );
              m_menuWindow.add(item);
              
              if ( i < 10 )
              {
                  item.setMnemonic( (char)( '1' + i ) );
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui/ProfileSampleFrame.java
  
  Index: ProfileSampleFrame.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.altprofile.profiler.gui;
  
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfileSampleDescriptor;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfileSampleListener;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfileSampleSnapshot;
  
  import java.awt.Dimension;
  
  import javax.swing.event.InternalFrameEvent;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:44 $
   * @since 4.1
   */
  class ProfileSampleFrame
      extends AbstractInternalFrame
      implements ProfileSampleListener, Runnable
  {
      private ProfileSampleDescriptor m_descriptor;
      private ProfilerManager m_profilerManager;
      private LineChart m_lineChart;
      
      private Thread m_runner;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      ProfileSampleFrame( String title,
                          ProfileSampleDescriptor descriptor,
                          ProfilerManager profilerManager,
                          ProfilerFrame profilerFrame )
      {
          super( title, true, true, true, true, profilerFrame );
          
          m_descriptor = descriptor;
          m_profilerManager = profilerManager;
          
          m_descriptor.addProfileSampleListener( this );
          
          // Decide on a line interval based on the interval of the sample.
          long interval = descriptor.getInterval();
          int hInterval;
          String format;
          String detailFormat;
          if ( interval < 1000 )
          {
              // Once per second.
              hInterval = (int)(1000 / interval);
              format = "{2}:{3}:{4}";
              detailFormat = "{0}/{1} {2}:{3}:{4}";
          }
          else if ( interval < 60000 )
          {
              // Once per minute.
              hInterval = (int)(60000 / interval);
              format = "{2}:{3}:{4}";
              detailFormat = "{0}/{1} {2}:{3}:{4}";
          }
          else if ( interval < 3600000 )
          {
              // Once per hour.
              hInterval = (int)(3600000 / interval);
              format = "{0}/{1} {2}:{3}";
              detailFormat = "{0}/{1} {2}:{3}";
          }
          else if ( interval < 86400000 )
          {
              // Once per day.
              hInterval = (int)(86400000 / interval);
              format = "{0}/{1}";
              detailFormat = "{0}/{1} {2}:{3}";
          }
          else
          {
              // Default to every 10 points.
              hInterval = 10;
              format = "{0}/{1} {2}:{3}";
              detailFormat = "{0}/{1} {2}:{3}";
          }
          
          m_lineChart = new LineChart( hInterval, (int)descriptor.getInterval() / 1000, format, detailFormat, 20 );
          
          getContentPane().add( m_lineChart );
          
          setSize(new Dimension(600, 120));
          
          update();
          
          m_runner = new Thread( this, descriptor.getName() + "_sampleFrame" );
          m_runner.start();
      }
      
      /*---------------------------------------------------------------
       * ProfileSampleListener Methods
       *-------------------------------------------------------------*/
      /**
       * Called by a ProfileSample whenever its value is changed.
       *
       * @param profileSampleName The name of the ProfileSample whose value was changed.
       * @param value The new value.
       * @param time The time that the ProfileSample value was changed.
       */
      public void setValue( String profileSampleName, int value, long time )
      {
          //System.out.println( "setValue(" + profileSampleName + ", " + value + ", " + time + ")" );
          
          //update();
      }
      
      /*---------------------------------------------------------------
       * InternalFrameListener Methods
       *-------------------------------------------------------------*/
      public void internalFrameClosed( InternalFrameEvent event )
      {
          m_descriptor.removeProfileSampleListener( this );
          
          m_runner = null;
          
          super.internalFrameClosed( event );
      }
      
      /*---------------------------------------------------------------
       * Runnable Methods
       *-------------------------------------------------------------*/
      public void run()
      {
          while( m_runner != null )
          {
              try
              {
                  Thread.sleep( 1000 );
              }
              catch ( InterruptedException e ) {}
              
              update();
          }
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      void update()
      {
          ProfileSampleSnapshot snapshot = m_descriptor.getSnapshot();
          
          int[] samples = snapshot.getSamples();
          
          m_lineChart.setValues( samples );
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/altprofile/profiler/gui/ProfilerFrame.java
  
  Index: ProfilerFrame.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.altprofile.profiler.gui;
  
  import java.awt.BorderLayout;
  
  import javax.swing.JDesktopPane;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  import javax.swing.SwingUtilities;
  import javax.swing.border.BevelBorder;
  
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilableDescriptor;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilerManager;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfilePointDescriptor;
  import org.apache.avalon.excalibur.altprofile.profiler.ProfileSampleDescriptor;
  
  /**
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/03/03 15:59:44 $
   * @since 4.1
   */
  public class ProfilerFrame
      extends JFrame
  {
      private ProfilerManager m_profilerManager;
      
      private JDesktopPane m_desktopPane;
      private MenuBar m_menuBar;
      
      /*---------------------------------------------------------------
  	 * Constructors
  	 *-------------------------------------------------------------*/
      /**
  	 * Creates a new ProfilerFrame.
  	 *
  	 * @param profilerManager The ProfilerManager which the ProfilerFrame's
  	 *                        data is obtained from.
  	 * @param title The title for the frame.
  	 */
      public ProfilerFrame( ProfilerManager profilerManager, String title )
      {
          super( title );
          
          m_profilerManager = profilerManager;
          
          init();
      }
      
      /*---------------------------------------------------------------
  	 * Methods
  	 *-------------------------------------------------------------*/
      private void init()
      {
          getContentPane().setLayout(new BorderLayout());
          
          // Create a DesktopPane and place it in a BevelBorder
          m_desktopPane = new DesktopPane();
          JPanel dBorder = new JPanel();
          dBorder.setBorder( new BevelBorder( BevelBorder.LOWERED ) );
          dBorder.setLayout( new BorderLayout() );
          dBorder.add( m_desktopPane, BorderLayout.CENTER );
          getContentPane().add(dBorder, BorderLayout.CENTER);
          
          // Create a Menu Bar
          m_menuBar = new MenuBar( this, m_profilerManager );
          setJMenuBar( m_menuBar );
          
          setLocation( 50, 50 );
          setSize( 640, 480 );
      }
      
      JDesktopPane getDesktopPane()
      {
          return m_desktopPane;
      }
      
  	void openProfileSampleFrame( final ProfilableDescriptor profilableDescriptor,
  								 final ProfilePointDescriptor profilePointDescriptor,
  								 final ProfileSampleDescriptor profileSampleDescriptor )
      {
          SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                  String title = profilableDescriptor.getDescription() + " : " +
  					profilePointDescriptor.getDescription() + " : " +
  					profileSampleDescriptor.getDescription();
                  
  				ProfileSampleFrame frame = new ProfileSampleFrame( title, profileSampleDescriptor,
  					m_profilerManager, ProfilerFrame.this );
  				
  				frame.addToDesktop( m_desktopPane );
  				frame.show();
              }
          });
      }
  }
  
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>