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>