Package org.apache.excalibur.instrument.manager

Source Code of org.apache.excalibur.instrument.manager.InstrumentableProxy

/*

============================================================================
                   The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of  source code must  retain the above copyright  notice,
    this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
    include  the following  acknowledgment:  "This product includes  software
    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
    Alternately, this  acknowledgment may  appear in the software itself,  if
    and wherever such third-party acknowledgments normally appear.
4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation" 
    must not be used to endorse or promote products derived from this  software
    without  prior written permission. For written permission, please contact
    apache@apache.org.
5. Products  derived from this software may not  be called "Apache", nor may
    "Apache" appear  in their name,  without prior written permission  of the
    Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
(INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software  consists of voluntary contributions made  by many individuals
on  behalf of the Apache Software  Foundation. For more  information on the
Apache Software Foundation, please see <http://www.apache.org/>.
*/
package org.apache.excalibur.instrument.manager;

import java.util.Arrays;
import java.util.Comparator;
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.configuration.DefaultConfiguration;
import org.apache.avalon.framework.logger.AbstractLogEnabled;

/**
* A InstrumentableProxy makes it easy for the InstrumentManager to manage
*  Instrumentables and their Instruments.
* <p>
* Not Synchronized.
*
* @author <a href="mailto:leif@tanukisoftware.com">Leif Mortenson</a>
* @version CVS $Revision: 1.4 $ $Date: 2003/02/25 16:28:16 $
* @since 4.1
*/
class InstrumentableProxy
    extends AbstractLogEnabled
    implements Configurable
{
    /** InstrumentManager which owns the proxy. */
    private DefaultInstrumentManager m_instrumentManager;
   
    /** The parent Instrumentable proxy or null if this is a top level
     *   Instrumentable. */
    private InstrumentableProxy m_parentInstrumentableProxy;
   
    /** Configured flag. */
    private boolean m_configured;

    /** Registered flag. */
    private boolean m_registered;

    /** The name used to identify a Instrumentable. */
    private String m_name;

    /** The description of the Instrumentable. */
    private String m_description;

    /** The Descriptor for the Instrumentable. */
    private InstrumentableDescriptorLocalImpl m_descriptor;

    /** Map of the Child InstrumentableProxies owned by this InstrumentableProxy. */
    private HashMap m_childInstrumentableProxies = new HashMap();

    /** Optimized array of the child InstrumentableProxies. */
    private InstrumentableProxy[] m_childInstrumentableProxyArray;

    /** Optimized array of the child InstrumentableDescriptorLocals. */
    private InstrumentableDescriptorLocal[] m_childInstrumentableDescriptorArray;

    /** Map of the InstrumentProxies owned by this InstrumentableProxy. */
    private HashMap m_instrumentProxies = new HashMap();

    /** Optimized array of the InstrumentProxies. */
    private InstrumentProxy[] m_instrumentProxyArray;

    /** Optimized array of the InstrumentDescriptorLocals. */
    private InstrumentDescriptorLocal[] m_instrumentDescriptorArray;
   
    /** State Version. */
    private int m_stateVersion;

    /*---------------------------------------------------------------
     * Constructors
     *-------------------------------------------------------------*/
    /**
     * Creates a new InstrumentableProxy.
     *
     * @param instrumentManager InstrumentManager which owns the proxy.
     * @param parentInstrumentableProxy The parent Instrumentable proxy or null
     *                                  if this is a top level Instrumentable.
     * @param name The name used to identify a Instrumentable.
     * @param description The description of the the Instrumentable.
     */
    InstrumentableProxy( DefaultInstrumentManager instrumentManager,
                         InstrumentableProxy parentInstrumentableProxy,
                         String name,
                         String description )
    {
        m_instrumentManager = instrumentManager;
        m_parentInstrumentableProxy = parentInstrumentableProxy;
        m_name = name;
        m_description = description;

        // Create the descriptor
        m_descriptor = new InstrumentableDescriptorLocalImpl( this );
    }

    /*---------------------------------------------------------------
     * Configurable Methods
     *-------------------------------------------------------------*/
    /**
     * Configures the Instrumentable.  Called from the ProfilerManager's
     *  configure method.  The class does not need to be configured to
     *  function correctly.
     *
     * @param configuration Instrumentable 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.  Default to the description from the constructor.
            m_description = configuration.getAttribute( "description", m_description );

            if( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "Configuring Instrumentable: " + m_name + " as \"" +
                                   m_description + "\"" );
            }

            m_configured = true;
           
            // Configure any child Instrumentables
            Configuration[] childConfs = configuration.getChildren( "instrumentable" );
            for( int i = 0; i < childConfs.length; i++ )
            {
                Configuration childConf = childConfs[ i ];
                String childName = childConf.getAttribute( "name" );
                String fullChildName = m_name + "." + childName;

                InstrumentableProxy childProxy = new InstrumentableProxy(
                    m_instrumentManager, this, fullChildName, childName );
                childProxy.enableLogging( getLogger() );
                childProxy.configure( childConf );
                m_childInstrumentableProxies.put( fullChildName, childProxy );

                // Clear the optimized arrays
                m_childInstrumentableProxyArray = null;
                m_childInstrumentableDescriptorArray = null;
            }
           
            // Configure any Instruments
            Configuration[] instrumentConfs = configuration.getChildren( "instrument" );
            for( int i = 0; i < instrumentConfs.length; i++ )
            {
                Configuration instrumentConf = instrumentConfs[ i ];
                String instrumentName = instrumentConf.getAttribute( "name" );
                String fullInstrumentName = m_name + "." + instrumentName;

                InstrumentProxy instrumentProxy =
                    new InstrumentProxy( this, fullInstrumentName, instrumentName );
                instrumentProxy.enableLogging( getLogger() );
                instrumentProxy.configure( instrumentConf );
                m_instrumentProxies.put( fullInstrumentName, instrumentProxy );

                // Clear the optimized arrays
                m_instrumentProxyArray = null;
                m_instrumentDescriptorArray = null;
            }
        }
    }

    /*---------------------------------------------------------------
     * Methods
     *-------------------------------------------------------------*/
    /**
     * Returns instrumentManager which owns the proxy.
     *
     * @return InstrumentManager which owns the proxy.
     */
    DefaultInstrumentManager getInstrumentManager()
    {
        return m_instrumentManager;
    }
   
    /**
     * Returns the parent InstrumentableProxy or null if this is a top level
     *  proxy.
     *
     * @return The parent InstrumentableProxy or null.
     */
    InstrumentableProxy getParentInstrumentableProxy()
    {
        return m_parentInstrumentableProxy;
    }
   
    /**
     * Returns true if the instrumentable was configured in the instrumentables
     *  section of the configuration.
     *
     * @return True if configured.
     */
    boolean isConfigured()
    {
        return m_configured;
    }

    /**
     * Returns true if the Instrumentable was registered with the Instrument
     *  Manager.
     *
     * @return True if registered.
     */
    boolean isRegistered()
    {
        return m_registered;
    }
   
    /**
     * Called by the InstrumentManager whenever an Instrumentable assigned to
     *  this proxy is registered.
     */
    void setRegistered()
    {
        m_registered = true;
    }
   
    /**
     * Gets the name for the Instrumentable.  The Instrumentable Name is used to
     *  uniquely identify the Instrumentable during the configuration of the
     *  Profiler and to gain access to a InstrumentableDescriptor through a
     *  ProfilerManager.
     *
     * @return The name used to identify a Instrumentable.
     */
    String getName()
    {
        return m_name;
    }

    /**
     * Sets the description for the instrumentable object.  This description will
     *  be set during the configuration of the profiler if a configuration
     *  exists for this Instrumentable.
     *
     * @param description The description of the Instrumentable.
     */
    void setDescription( String description )
    {
        m_description = description;
    }

    /**
     * Gets the description of the Instrumentable.
     *
     * @return The description of the Instrumentable.
     */
    String getDescription()
    {
        return m_description;
    }

    /**
     * Returns a Descriptor for the Instrumentable.
     *
     * @return A Descriptor for the Instrumentable.
     */
    InstrumentableDescriptorLocal getDescriptor()
    {
        return m_descriptor;
    }

    /*---------------------------------------------------------------
     * Methods (child Instrumentables)
     *-------------------------------------------------------------*/
    /**
     * Adds a child InstrumentableProxy to the Instrumentable.  This method
     *  will be called during the configuration phase of the Profiler if an
     *  element defining the child Instrumentable exists, or if the
     *  Instrumentable registers itself with the InstrumentManager as it
     *  is running.
     * <p>
     * This method should never be called for child Instrumentables which
     *  have already been added.
     *
     * @param childInstrumentableProxy Child InstrumentableProxy to be added.
     */
    void addChildInstrumentableProxy( InstrumentableProxy childInstrumentableProxy )
    {
        synchronized( this )
        {
            m_childInstrumentableProxies.put(
                childInstrumentableProxy.getName(), childInstrumentableProxy );

            // Clear the optimized arrays
            m_childInstrumentableProxyArray = null;
            m_childInstrumentableDescriptorArray = null;
        }
       
        stateChanged();
    }

    /**
     * Returns a child InstrumentableProxy based on its name or the name of any
     *  of its children.
     *
     * @param childInstrumentableName Name of the child Instrumentable being
     *                                requested.
     *
     * @return The requested child InstrumentableProxy or null if does not
     *         exist.
     */
    InstrumentableProxy getChildInstrumentableProxy( String childInstrumentableName )
    {
        synchronized( this )
        {
            String name = childInstrumentableName;
            while( true )
            {
                InstrumentableProxy proxy =
                    (InstrumentableProxy)m_childInstrumentableProxies.get( name );
                if( proxy != null )
                {
                    return proxy;
                }

                // Assume this is a child name and try looking with the parent name.
                int pos = name.lastIndexOf( '.' );
                if( pos > 0 )
                {
                    name = name.substring( 0, pos );
                }
                else
                {
                    return null;
                }
            }
        }
    }

    /**
     * Returns an array of Proxies to the child Instrumentables in this
     *  Instrumentable.
     *
     * @return An array of Proxies to the child Instrumentables in this
     *         Instrumentable.
     */
    InstrumentableProxy[] getChildInstrumentableProxies()
    {
        InstrumentableProxy[] proxies = m_childInstrumentableProxyArray;
        if( proxies == null )
        {
            proxies = updateChildInstrumentableProxyArray();
        }
       
        return proxies;
    }

    /**
     * Returns an array of Descriptors for the child Instrumentables in this
     *  Instrumentable.
     *
     * @return An array of Descriptors for the child Instrumentables in this
     *         Instrumentable.
     */
    InstrumentableDescriptorLocal[] getChildInstrumentableDescriptors()
    {
        InstrumentableDescriptorLocal[] descriptors = m_childInstrumentableDescriptorArray;
        if( descriptors == null )
        {
            descriptors = updateChildInstrumentableDescriptorArray();
        }
       
        return descriptors;
    }

    /**
     * Updates the cached array of child InstrumentableProxies taking
     *  synchronization into account.
     *
     * @return An array of the child InstrumentableProxies.
     */
    private InstrumentableProxy[] updateChildInstrumentableProxyArray()
    {
        synchronized( this )
        {
            m_childInstrumentableProxyArray =
                new InstrumentableProxy[ m_childInstrumentableProxies.size() ];
            m_childInstrumentableProxies.values().toArray( m_childInstrumentableProxyArray );

            // Sort the array.  This is not a performance problem because this
            //  method is rarely called and doing it here saves cycles in the
            //  client.
            Arrays.sort( m_childInstrumentableProxyArray, new Comparator()
                {
                    public int compare( Object o1, Object o2 )
                    {
                        return ((InstrumentableProxy)o1).getDescription().
                            compareTo( ((InstrumentableProxy)o2).getDescription() );
                    }
                   
                    public boolean equals( Object obj )
                    {
                        return false;
                    }
                } );
           
            return m_childInstrumentableProxyArray;
        }
    }

    /**
     * Updates the cached array of child InstrumentableDescriptorLocals taking
     *  synchronization into account.
     *
     * @return An array of the child InstrumentableDescriptorLocals.
     */
    private InstrumentableDescriptorLocal[] updateChildInstrumentableDescriptorArray()
    {
        synchronized( this )
        {
            if( m_childInstrumentableProxyArray == null )
            {
                updateChildInstrumentableProxyArray();
            }

            m_childInstrumentableDescriptorArray =
                new InstrumentableDescriptorLocal[ m_childInstrumentableProxyArray.length ];
            for( int i = 0; i < m_childInstrumentableProxyArray.length; i++ )
            {
                m_childInstrumentableDescriptorArray[ i ] =
                    m_childInstrumentableProxyArray[ i ].getDescriptor();
            }

            return m_childInstrumentableDescriptorArray;
        }
    }

    /*---------------------------------------------------------------
     * Methods (Instruments)
     *-------------------------------------------------------------*/
    /**
     * Adds a InstrumentProxy to the Instrumentable.  This method will be
     *  called during the configuration phase of the Profiler if an element
     *  defining the Instrument exists, or if the Instrument registers
     *  itself with the ProfilerManager as it is running.
     * <p>
     * This method should never be called for Instruments which have already
     *  been added.
     *
     * @param instrumentProxy InstrumentProxy to be added.
     */
    void addInstrumentProxy( InstrumentProxy instrumentProxy )
    {
        synchronized( this )
        {
            m_instrumentProxies.put( instrumentProxy.getName(), instrumentProxy );

            // Clear the optimized arrays
            m_instrumentProxyArray = null;
            m_instrumentDescriptorArray = null;
        }
       
        stateChanged();
    }

    /**
     * Returns a InstrumentProxy based on its name or the name of any
     *  of its children.
     *
     * @param instrumentName Name of the Instrument being requested.
     *
     * @return The requested InstrumentProxy or null if does not exist.
     */
    InstrumentProxy getInstrumentProxy( String instrumentName )
    {
        synchronized( this )
        {
            String name = instrumentName;
            while( true )
            {
                InstrumentProxy proxy = (InstrumentProxy)m_instrumentProxies.get( name );
                if( proxy != null )
                {
                    return proxy;
                }

                // Assume this is a child name and try looking with the parent name.
                int pos = name.lastIndexOf( '.' );
                if( pos > 0 )
                {
                    name = name.substring( 0, pos );
                }
                else
                {
                    return null;
                }
            }
        }
    }

    /**
     * Returns an array of Proxies to the Instruments in the Instrumentable.
     *
     * @return An array of Proxies to the Instruments in the Instrumentable.
     */
    InstrumentProxy[] getInstrumentProxies()
    {
        InstrumentProxy[] proxies = m_instrumentProxyArray;
        if( proxies == null )
        {
            proxies = updateInstrumentProxyArray();
        }
        return proxies;
    }

    /**
     * Returns an array of Descriptors for the Instruments in the Instrumentable.
     *
     * @return An array of Descriptors for the Instruments in the Instrumentable.
     */
    InstrumentDescriptorLocal[] getInstrumentDescriptors()
    {
        InstrumentDescriptorLocal[] descriptors = m_instrumentDescriptorArray;
        if( descriptors == null )
        {
            descriptors = updateInstrumentDescriptorArray();
        }
        return descriptors;
    }
   
    /**
     * Returns the stateVersion of the instrumentable.  The state version
     *  will be incremented each time any of the configuration of the
     *  instrumentable or any of its children is modified.
     * Clients can use this value to tell whether or not anything has
     *  changed without having to do an exhaustive comparison.
     *
     * @return The state version of the instrumentable.
     */
    int getStateVersion()
    {
        return m_stateVersion;
    }

    /**
     * Updates the cached array of InstrumentProxies taking
     *  synchronization into account.
     *
     * @return An array of the InstrumentProxies.
     */
    private InstrumentProxy[] updateInstrumentProxyArray()
    {
        synchronized( this )
        {
            m_instrumentProxyArray = new InstrumentProxy[ m_instrumentProxies.size() ];
            m_instrumentProxies.values().toArray( m_instrumentProxyArray );

            // Sort the array.  This is not a performance problem because this
            //  method is rarely called and doing it here saves cycles in the
            //  client.
            Arrays.sort( m_instrumentProxyArray, new Comparator()
                {
                    public int compare( Object o1, Object o2 )
                    {
                        return ((InstrumentProxy)o1).getDescription().
                            compareTo( ((InstrumentProxy)o2).getDescription() );
                    }
                   
                    public boolean equals( Object obj )
                    {
                        return false;
                    }
                } );
           
            return m_instrumentProxyArray;
        }
    }

    /**
     * Updates the cached array of InstrumentDescriptorLocals taking
     *  synchronization into account.
     *
     * @return An array of the InstrumentDescriptorLocals.
     */
    private InstrumentDescriptorLocal[] updateInstrumentDescriptorArray()
    {
        synchronized( this )
        {
            if( m_instrumentProxyArray == null )
            {
                updateInstrumentProxyArray();
            }

            m_instrumentDescriptorArray =
                new InstrumentDescriptorLocal[ m_instrumentProxyArray.length ];
            for( int i = 0; i < m_instrumentProxyArray.length; i++ )
            {
                m_instrumentDescriptorArray[ i ] = m_instrumentProxyArray[ i ].getDescriptor();
            }

            return m_instrumentDescriptorArray;
        }
    }

    /**
     * Saves the current state into a Configuration.
     *
     * @return The state as a Configuration.  Returns null if the configuration
     *         would not contain any information.
     */
    Configuration saveState()
    {
        boolean empty = true;
        DefaultConfiguration state = new DefaultConfiguration( "instrumentable", "-" );
        state.setAttribute( "name", m_name );

        // Save the child Instrumentables
        InstrumentableProxy[] childProxies = getChildInstrumentableProxies();
        for( int i = 0; i < childProxies.length; i++ )
        {
            Configuration childState = childProxies[ i ].saveState();
            if ( childState != null )
            {
                empty = false;
                state.addChild( childState );
            }
        }

        // Save the direct Instruments
        InstrumentProxy[] proxies = getInstrumentProxies();
        for( int i = 0; i < proxies.length; i++ )
        {
            Configuration childState = proxies[ i ].saveState();
            if ( childState != null )
            {
                empty = false;
                state.addChild( childState );
            }
        }

        // Only return a state if it contains information.
        if ( empty )
        {
            state = null;
        }
        return state;
    }

    /**
     * Loads the state into the Instrumentable.
     *
     * @param state Configuration object to load state from.
     *
     * @throws ConfigurationException If there were any problems loading the
     *                                state.
     */
    void loadState( Configuration state ) throws ConfigurationException
    {
        synchronized( this )
        {
            // Load the child Instrumentables
            Configuration[] childConfs = state.getChildren( "instrumentable" );
            for( int i = 0; i < childConfs.length; i++ )
            {
                Configuration childConf = childConfs[ i ];
                String fullChildName = childConf.getAttribute( "name" );
                InstrumentableProxy childProxy = getChildInstrumentableProxy( fullChildName );
                if( childProxy == null )
                {
                    // The child Instrumentable was in the state file, but has
                    //  not yet been registered.  It is possible that it will
                    //  be registered at a later time.  For now it needs to be
                    //  created.
                    String childName = ( fullChildName.startsWith( m_name + "." ) ?
                        fullChildName.substring( m_name.length() + 1 ) : "BADNAME." + fullChildName );
                   
                    childProxy = new InstrumentableProxy(
                        m_instrumentManager, this, fullChildName, childName );
                    childProxy.enableLogging( getLogger() );
                    m_childInstrumentableProxies.put( fullChildName, childProxy );
   
                    // Clear the optimized arrays
                    m_childInstrumentableProxyArray = null;
                    m_childInstrumentableDescriptorArray = null;
                }
                childProxy.loadState( childConf );
            }
           
            // Load the direct Instruments
            Configuration[] instrumentConfs = state.getChildren( "instrument" );
            for( int i = 0; i < instrumentConfs.length; i++ )
            {
                Configuration instrumentConf = instrumentConfs[ i ];
                String fullInstrumentName = instrumentConf.getAttribute( "name" );
                InstrumentProxy instrumentProxy = getInstrumentProxy( fullInstrumentName );
                if( instrumentProxy == null )
                {
                    // The Instrument was in the state file, but has not yet been
                    //  registered.  It is possible that it will be registered
                    //  at a later time.  For now it needs to be created.
                    String instrumentName = ( fullInstrumentName.startsWith( m_name + "." ) ?
                        fullInstrumentName.substring( m_name.length() + 1 ) : "BADNAME." + fullInstrumentName );
                   
                    instrumentProxy =
                        new InstrumentProxy( this, fullInstrumentName, instrumentName );
                    instrumentProxy.enableLogging( getLogger() );
                    m_instrumentProxies.put( fullInstrumentName, instrumentProxy );
   
                    // Clear the optimized arrays
                    m_instrumentProxyArray = null;
                    m_instrumentDescriptorArray = null;
                }
                instrumentProxy.loadState( instrumentConf );
            }
        }
       
        stateChanged();
    }
   
    /**
     * Called whenever the state of the instrumentable is changed.
     */
    protected void stateChanged()
    {
        m_stateVersion++;
       
        // Propagate to the parent
        if ( m_parentInstrumentableProxy == null )
        {
            // This is a top level Instrumentable
            m_instrumentManager.stateChanged();
        }
        else
        {
            m_parentInstrumentableProxy.stateChanged();
        }
    }
}
TOP

Related Classes of org.apache.excalibur.instrument.manager.InstrumentableProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.