avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcconn...@apache.org
Subject cvs commit: jakarta-avalon/src/proposal/service ServiceManager.java ServiceException.java Serviceable.java LifecycleHelper.java DefaultServiceManager.java
Date Sun, 10 Feb 2002 05:39:54 GMT
mcconnell    02/02/09 21:39:54

  Added:       src/proposal/service ServiceManager.java
                        ServiceException.java Serviceable.java
                        LifecycleHelper.java DefaultServiceManager.java
  Log:
  proposal for ComponentManager/Composable replacement
  
  Revision  Changes    Path
  1.1                  jakarta-avalon/src/proposal/service/ServiceManager.java
  
  Index: ServiceManager.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.framework.service;
  
  /**
   * A <code>ServiceManager</code> selects <code>Object</code>s based
on a
   * role.  The contract is that all the <code>Object</code>s implement the
   * differing roles and there is one <code>Object</code> per role.  If you
   * need to select on of many <code>Object</code>s that implement the same
   * role, then you need to use a <code>ServiceSelector</code>.  Roles are
   * usually the full interface name.
   *
   * A role is better understood by the analogy of a play.  There are many
   * different roles in a script.  Any actor or actress can play any given part
   * and you get the same results (phrases said, movements made, etc.).  The exact
   * nuances of the performance is different.
   *
   * Below is a list of things that might be considered the different roles:
   *
   * <ul>
   *   <li> InputAdaptor and OutputAdaptor</li>
   *   <li> Store and Spool</li>
   * </ul>
   *
   * The <code>ServiceManager</code> does not specify the methodology of
   * getting the <code>Object</code>, merely the interface used to get it.
   * Therefore the <code>ServiceManager</code> can be implemented with a
   * factory pattern, an object pool, or a simple Hashtable.
   *
   * @see org.apache.avalon.framework.service.Serviceable
   * @see org.apache.avalon.framework.service.ServiceSelector
   *
   * @author <a href="mailto:scoobie@betaversion.org">Federico Barbieri</a>
   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   * @author <a href="mailto:fumagalli@exoffice.com">Pierpaolo Fumagalli</a>
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   */
  public interface ServiceManager
  {
      /**
       * Get the <code>Object</code> associated with the given role.  For
       * instance, If the <code>ServiceManager</code> had a
       * <code>LoggerComponent</code> stored and referenced by role, I would use
       * the following call:
       * <pre>
       * try
       * {
       *     MyComponent log;
       *     myComponent = (MyComponent) manager.lookup(MyComponent.ROLE);
       * }
       * catch (...)
       * {
       *     ...
       * }
       * </pre>
       *
       * @param name The role name of the <code>Object</code> to retrieve.
       * @exception ServiceException if an error occurs
       */
      Object lookup( String role )
          throws ServiceException;
  
      /**
       * Check to see if a <code>Object</code> exists for a role.
       *
       * @param role  a string identifying the role to check.
       * @return True if the object exists, False if it does not.
       */
      boolean hasService( String role );
  
      /**
       * Return the <code>Object</code> when you are finished with it.  This
       * allows the <code>ServiceManager</code> to handle the End-Of-Life Lifecycle
       * events associated with the Object.  Please note, that no Exceptions
       * should be thrown at this point.  This is to allow easy use of the
       * ServiceManager system without having to trap Exceptions on a release.
       *
       * @param object The Object we are releasing.
       */
      void release( Object object );
  }
  
  
  
  1.1                  jakarta-avalon/src/proposal/service/ServiceException.java
  
  Index: ServiceException.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.framework.service;
  
  import org.apache.avalon.framework.CascadingException;
  
  /**
   * The exception thrown to indicate a problem with service.
   * It is usually thrown by ServiceManager or ServiceSelector.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:fumagalli@exoffice.com">Pierpaolo Fumagalli</a>
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   */
  public class ServiceException
      extends CascadingException
  {
      /**
       * Construct a new <code>ServiceException</code> instance.
       *
       * @param message the exception message
       * @param throwable the throwable
       */
      public ServiceException( final String message, final Throwable throwable )
      {
          super( message, throwable );
      }
  
      /**
       * Construct a new <code>ServiceException</code> instance.
       *
       * @param message the exception message
       */
      public ServiceException( final String message )
      {
          super( message, null );
      }
  }
  
  
  
  1.1                  jakarta-avalon/src/proposal/service/Serviceable.java
  
  Index: Serviceable.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.framework.service;
  
  /**
   * A servicable is a class that need to connect to software components using
   * a "role" abstraction, thus not depending on particular implementations
   * but on behavioral interfaces.
   * <br />
   *
   * The contract surrounding a <code>Serviceable</code> is that it is a user.
   * The <code>Serviceable</code> is able to use <code>Object</code>s
managed
   * by the <code>ServiceManager</code> it was initialized with.  As part
   * of the contract with the system, the instantiating entity must call
   * the <code>compose</code> method before the <code>Serviceable</code>

   * can be considered valid. 
   *
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   */
  public interface Serviceable
  {
      /**
       * Pass the <code>ServiceManager</code> to the <code>servicable</code>.
       * The <code>Servicable</code> implementation should use the specified
       * <code>ServiceManager</code> to acquire the components it needs for
       * execution.
       *
       * @param manager The <code>ServiceManager</code> which this
       *                <code>Servicable</code> uses.
       */
      void service( ServiceManager manager )
          throws ServiceException;
  }
  
  
  
  1.1                  jakarta-avalon/src/proposal/service/LifecycleHelper.java
  
  Index: LifecycleHelper.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.phoenix.components.application;
  
  import org.apache.avalon.excalibur.container.State;
  import org.apache.avalon.excalibur.i18n.ResourceManager;
  import org.apache.avalon.excalibur.i18n.Resources;
  import org.apache.avalon.framework.CascadingException;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.component.DefaultComponentManager;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.Serviceable;
  import org.apache.avalon.framework.service.DefaultServiceManager;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.logger.LogKitLogger;
  import org.apache.avalon.framework.logger.Loggable;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.parameters.Parameterizable;
  import org.apache.avalon.framework.parameters.ParameterException;
  import org.apache.avalon.phoenix.Block;
  import org.apache.avalon.phoenix.BlockContext;
  import org.apache.avalon.phoenix.BlockEvent;
  import org.apache.avalon.phoenix.BlockListener;
  import org.apache.avalon.phoenix.ApplicationListener;
  import org.apache.avalon.phoenix.ApplicationEvent;
  import org.apache.avalon.phoenix.interfaces.Application;
  import org.apache.avalon.phoenix.interfaces.ApplicationContext;
  import org.apache.avalon.phoenix.metadata.BlockListenerMetaData;
  import org.apache.avalon.phoenix.metadata.BlockMetaData;
  import org.apache.avalon.phoenix.metadata.DependencyMetaData;
  import org.apache.avalon.phoenix.metainfo.ServiceDescriptor;
  
  /**
   * This is a class to help an Application manage lifecycle of
   * <code>Blocks</code> and <code>BlockListeners</code>. The
   * class will run each individual Entry through each lifecycle stage,
   * and manage erros in a consistent way.
   *
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   */
  class LifecycleHelper
      extends AbstractLogEnabled
  {
      private static final Resources REZ =
          ResourceManager.getPackageResources( LifecycleHelper.class );
  
      //Constants to designate stages
      private final static int STAGE_CREATE = 0;
      private final static int STAGE_LOGGER = 1;
      private final static int STAGE_CONTEXT = 2;
      private final static int STAGE_COMPOSE = 3;
      private final static int STAGE_CONFIG = 4;
      private final static int STAGE_PARAMETER = 5;
      private final static int STAGE_INIT = 6;
      private final static int STAGE_START = 7;
      private final static int STAGE_STOP = 8;
      private final static int STAGE_DISPOSE = 9;
      private final static int STAGE_DESTROY = 10;
  
      //Constants to designate type of component
      private final static int TYPE_BLOCK = 0;
      private final static int TYPE_LISTENER = 1;
  
      ///Frame in which block executes
      private ApplicationContext m_context;
  
      /**
       * The Application which this phase is associated with.
       * Required to build a ComponentManager.
       */
      private Application m_application;
  
      /**
       * Object to support notification of BlockListeners.
       */
      private BlockListenerSupport m_blockListenerSupport = new BlockListenerSupport();
  
      /**
       * Object to support notification of ApplicationListeners.
       */
      private ApplicationListenerSupport m_applicationListenerSupport = new ApplicationListenerSupport();
  
      /**
       * Construct helper object for specified application,
       * in specified frame.
       *
       * @param application the Application that this object is helper to
       * @param context the ApplicationContext in which this helper operates
       */
      protected LifecycleHelper( final Application application,
                                 final ApplicationContext context )
      {
          m_application = application;
          m_context = context;
      }
  
      /**
       * Method to run a <code>BlockListener</code> through it's startup phase.
       * This will involve creation of BlockListener object and configuration of
       * object if appropriate.
       *
       * @param metaData the BlockListenerMetaData
       * @exception Exception if an error occurs when listener passes
       *            through a specific lifecycle stage
       */
      public void startupListener( final BlockListenerMetaData metaData )
          throws Exception
      {
          final String name = metaData.getName();
  
          final ClassLoader classLoader = m_context.getClassLoader();
          final Class clazz = classLoader.loadClass( metaData.getClassname() );
          final BlockListener listener = (BlockListener)clazz.newInstance();
  
          if( listener instanceof LogEnabled )
          {
              final Logger logger = new LogKitLogger( m_context.getLogger( name ) );
              ( (LogEnabled)listener ).enableLogging( logger );
          }
  
          if( listener instanceof Configurable )
          {
              final Configuration configuration = getConfiguration( name, TYPE_LISTENER );
              ( (Configurable)listener ).configure( configuration );
          }
  
          // As ApplicationListners are BlockListeners then this is applicable for all
          m_blockListenerSupport.addBlockListener( listener );
  
          // However onky ApplicationListners can avail of block events.
          if (listener instanceof ApplicationListener)
          {
              m_applicationListenerSupport.addApplicationListener( (ApplicationListener) listener
);
          }
  
  
  
      }
  
      public void applicationStarting(ApplicationEvent appEvent) throws Exception
      {
          m_applicationListenerSupport.applicationStarting(appEvent);
      }
  
      public void applicationStarted()
      {
          m_applicationListenerSupport.applicationStarted();
      }
  
      public void applicationStopping()
      {
          m_applicationListenerSupport.applicationStopping();
      }
  
      public void applicationStopped()
      {
          m_applicationListenerSupport.applicationStopped();
      }
  
      public void applicationFailure(Exception causeOfFailure)
      {
          m_applicationListenerSupport.applicationFailure(causeOfFailure);
      }
  
      /**
       * Method to run a <code>Block</code> through it's startup phase.
       * This will involve notification of <code>BlockListener</code>
       * objects, creation of the Block/Block Proxy object, calling the startup
       * Avalon Lifecycle methods and updating State property of BlockEntry.
       * Errors that occur during shutdown will be logged appropriately and
       * cause exceptions with useful messages to be raised.
       *
       * @param entry the entry containing Block
       * @exception Exception if an error occurs when block passes
       *            through a specific lifecycle stage
       */
      public void startup( final BlockEntry entry )
          throws Exception
      {
          final BlockMetaData metaData = entry.getMetaData();
          final String name = metaData.getName();
  
          //The number of stage currently at
          //(Used in constructing error messages)
          int stage = 0;
  
          try
          {
              //Creation stage
              stage = STAGE_CREATE;
              notice( name, stage );
              final Block block = createBlock( metaData );
  
              //LogEnabled stage
              stage = STAGE_LOGGER;
              if( block instanceof Loggable )
              {
                  notice( name, stage );
                  ( (Loggable)block ).setLogger( m_context.getLogger( name ) );
              }
              else if( block instanceof LogEnabled )
              {
                  notice( name, stage );
                  final Logger logger = new LogKitLogger( m_context.getLogger( name ) );
                  ( (LogEnabled)block ).enableLogging( logger );
              }
  
              //Contextualize stage
              stage = STAGE_CONTEXT;
              if( block instanceof Contextualizable )
              {
                  notice( name, stage );
                  final BlockContext context = createBlockContext( name );
                  ( (Contextualizable)block ).contextualize( context );
              }
  
              //Composition stage
              stage = STAGE_COMPOSE;
              if( block instanceof Composable )
              {
                  notice( name, stage );
                  final ComponentManager componentManager = createComponentManager( metaData
);
                  ( (Composable)block ).compose( componentManager );
              }
              else if( block instanceof Serviceable )
              {
                  notice( name, stage );
                  final ServiceManager manager = createServiceManager( metaData );
                  ( (Serviceable)block ).service( manager );
              }
  
              //Configuring stage
              stage = STAGE_CONFIG;
              if( block instanceof Configurable )
              {
                  notice( name, stage );
                  final Configuration configuration = getConfiguration( name, TYPE_BLOCK );
                  ( (Configurable)block ).configure( configuration );
              }
  
              //Parameterizing stage
              stage = STAGE_PARAMETER;
              if( block instanceof Parameterizable )
              {
                  notice( name, stage );
                  final Parameters parameters = 
                      Parameters.fromConfiguration( getConfiguration( name, TYPE_BLOCK ) );
                  parameters.makeReadOnly();
                  ( (Parameterizable)block ).parameterize( parameters );
              }
  
              //Initialize stage
              stage = STAGE_INIT;
              if( block instanceof Initializable )
              {
                  notice( name, stage );
                  ( (Initializable)block ).initialize();
              }
  
              //Start stage
              stage = STAGE_START;
              if( block instanceof Startable )
              {
                  notice( name, stage );
                  ( (Startable)block ).start();
              }
  
              entry.setState( State.STARTED );
              entry.setBlock( block );
  
              exportBlock( metaData, block );
              
              final Block proxy = entry.getProxy();
              final BlockEvent event =
                  new BlockEvent( name, proxy, metaData.getBlockInfo() );
              m_blockListenerSupport.blockAdded( event );
          }
          catch( final Throwable t )
          {
              entry.setState( State.FAILED );
              fail( name, stage, t );
          }
      }
  
      /**
       * Method to run a <code>Block</code> through it's shutdown phase.
       * This will involve notification of <code>BlockListener</code>
       * objects, invalidating the proxy object, calling the shutdown
       * Avalon Lifecycle methods and updating State property of BlockEntry.
       * Errors that occur during shutdown will be logged appropraitely.
       *
       * @param entry the entry containing Block
       */
      public void shutdown( final BlockEntry entry )
      {
          final BlockMetaData metaData = entry.getMetaData();
          final String name = metaData.getName();
  
          final BlockEvent event =
              new BlockEvent( name, entry.getProxy(), metaData.getBlockInfo() );
          m_blockListenerSupport.blockRemoved( event );
  
          final Block block = entry.getBlock();
  
          //Remove block from Management system
          unexportBlock( metaData, block );
  
          //Invalidate entry. This will invalidate
          //and null out Proxy object aswell as nulling out
          //block property
          entry.invalidate();
  
          //Stoppable stage
          if( block instanceof Startable )
          {
              notice( name, STAGE_STOP );
              try
              {
                  entry.setState( State.STOPPING );
                  ( (Startable)block ).stop();
                  entry.setState( State.STOPPED );
              }
              catch( final Throwable t )
              {
                  entry.setState( State.FAILED );
                  safeFail( name, STAGE_STOP, t );
              }
          }
  
          //Disposable stage
          if( block instanceof Disposable )
          {
              notice( name, STAGE_DISPOSE );
              try
              {
                  entry.setState( State.DESTROYING );
                  ( (Disposable)block ).dispose();
              }
              catch( final Throwable t )
              {
                  entry.setState( State.FAILED );
                  safeFail( name, STAGE_DISPOSE, t );
              }
          }
  
          notice( name, STAGE_DESTROY );
          entry.setState( State.DESTROYED );
      }
  
      /**
       * Export the services of block, declared to be management 
       * services, into management system.
       */
      private void exportBlock( final BlockMetaData metaData, 
                                final Block block )
          throws CascadingException
      {
          final ServiceDescriptor[] services = metaData.getBlockInfo().getManagementAccessPoints();
          final String name = metaData.getName();
          final ClassLoader classLoader = block.getClass().getClassLoader();
  
          for( int i = 0; i < services.length; i++ )
          {
              final ServiceDescriptor service = services[ i ];
              try
              {
                  final Class clazz = classLoader.loadClass( service.getName() );
                  m_context.exportObject( name, clazz, block );
              }
              catch( final Exception e )
              {
                  final String reason = e.toString();
                  final String message =
                      REZ.getString( "export.error", name, service.getName(), reason );
                  getLogger().error( message );
                  throw new CascadingException( message, e );
              }
          }
      }
  
      /**
       * Unxport the services of block, declared to be management 
       * services, into management system.
       */
      private void unexportBlock( final BlockMetaData metaData, 
                                  final Block block )
      {
          final ServiceDescriptor[] services = metaData.getBlockInfo().getManagementAccessPoints();
          final String name = metaData.getName();
          final ClassLoader classLoader = block.getClass().getClassLoader();
  
          for( int i = 0; i < services.length; i++ )
          {
              final ServiceDescriptor service = services[ i ];
              try
              {
                  final Class clazz = classLoader.loadClass( service.getName() );
                  m_context.unexportObject( name, clazz );
              }
              catch( final Exception e )
              {
                  final String reason = e.toString();
                  final String message =
                      REZ.getString( "unexport.error", name, service.getName(), reason );
                  getLogger().error( message );
              }
          }
      }
  
      /**
       * Utility method to create a <code>Block</code> object
       * from specified BlockMetaData.
       *
       * @param metaData the BlockMetaData
       * @return the newly created Block object
       * @exception Exception if an error occurs
       */
      private Block createBlock( final BlockMetaData metaData )
          throws Exception
      {
          final ClassLoader classLoader = m_context.getClassLoader();
          final Class clazz = classLoader.loadClass( metaData.getClassname() );
          return (Block)clazz.newInstance();
      }
  
      /**
       * Create a BlockContext object for Block with specified name.
       *
       * @param name the name of Block
       * @return the created BlockContext
       */
      private BlockContext createBlockContext( final String name )
      {
          final DefaultBlockContext context = new DefaultBlockContext( name, m_context );
          setupLogger( context );
          return context;
      }
  
      /**
       * Retrieve a configuration for specified component.
       * If the configuration is missing then a exception
       * is raised with an appropraite error message.
       *
       * @param name the name of component
       * @return the Configuration object
       * @exception ConfigurationException if an error occurs
       */
      private Configuration getConfiguration( final String name, final int type )
          throws ConfigurationException
      {
          try
          {
              return m_context.getConfiguration( name );
          }
          catch( final ConfigurationException ce )
          {
              //Note that this shouldn't ever happen once we
              //create a Config validator
              final String message =
                  REZ.getString( "missing-configuration", new Integer( type ), name );
              throw new ConfigurationException( message, ce );
          }
      }
  
      /**
       * Create a <code>ComponentManager</code> object for a
       * specific <code>Block</code>. This requires that for
       * each dependency a reference to providing <code>Block</code>
       * is aaqiured from the Application and placing it in
       * <code>ComponentManager</code> under the correct name.
       *
       * @param metaData the BlockMetaData representing block
       * @return the created ComponentManager
       */
      private ComponentManager createComponentManager( final BlockMetaData metaData )
      {
          final DefaultComponentManager componentManager = new DefaultComponentManager();
          final DependencyMetaData[] roles = metaData.getDependencies();
  
          for( int i = 0; i < roles.length; i++ )
          {
              final DependencyMetaData role = roles[ i ];
              final Block dependency = m_application.getBlock( role.getName() );
              componentManager.put( role.getRole(), dependency );
          }
  
          return componentManager;
      }
  
      private ServiceManager createServiceManager( final BlockMetaData metaData )
      {
          final DefaultServiceManager manager = new DefaultServiceManager();
          final DependencyMetaData[] roles = metaData.getDependencies();
  
          for( int i = 0; i < roles.length; i++ )
          {
              final DependencyMetaData role = roles[ i ];
              final Block dependency = m_application.getBlock( role.getName() );
              manager.put( role.getRole(), dependency );
          }
  
          return manager;
      }
  
      /**
       * Utility method to report that a lifecycle stage is about to be processed.
       *
       * @param name the name of block that caused failure
       * @param stage the stage
       */
      private void notice( final String name, final int stage )
      {
          if( getLogger().isDebugEnabled() )
          {
              final String message =
                  REZ.getString( "lifecycle-stage.notice", name, new Integer( stage ) );
              getLogger().debug( message );
          }
      }
  
      /**
       * Utility method to report that there was an error processing
       * specified lifecycle stage.
       *
       * @param name the name of block that caused failure
       * @param stage the stage
       * @param t the exception thrown
       */
      private void safeFail( final String name, final int stage, final Throwable t )
      {
          //final String reason = t.getMessage();
          final String reason = t.toString();
          final String message =
              REZ.getString( "lifecycle-fail.error", name, new Integer( stage ), reason );
          getLogger().error( message );
      }
  
      /**
       * Utility method to report that there was an error processing
       * specified lifecycle stage. It will also rethrow an exception
       * with a better error message.
       *
       * @param name the name of block that caused failure
       * @param stage the stage
       * @param t the exception thrown
       * @exception Exception containing error
       */
      private void fail( final String name, final int stage, final Throwable t )
          throws Exception
      {
          //final String reason = t.getMessage();
          final String reason = t.toString();
          final String message =
              REZ.getString( "lifecycle-fail.error", name, new Integer( stage ), reason );
          getLogger().error( message );
          throw new CascadingException( message, t );
      }
  }
  
  
  
  1.1                  jakarta-avalon/src/proposal/service/DefaultServiceManager.java
  
  Index: DefaultServiceManager.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.framework.service;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  /**
   * This class is a static implementation of a ServiceManager. Allow ineritance
   * and extension so you can generate a tree of ServiceManager each defining
   * Object scope.
   *
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:peter@apache.org">Peter Donald</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   */
  public class DefaultServiceManager
      implements ServiceManager
  {
      private final HashMap               m_components = new HashMap();
      private final ServiceManager        m_parent;
      private boolean                     m_readOnly;
  
      /**
       * Construct ServiceManager with no parent.
       *
       */
      public DefaultServiceManager()
      {
          this( null );
      }
  
      /**
       * Construct ServiceManager with specified parent.
       *
       * @param parent the ServiceManager parent
       */
      public DefaultServiceManager( final ServiceManager parent )
      {
          m_parent = parent;
      }
  
      /**
       * Retrieve Object by role from ServiceManager.
       *
       * @param role the role
       * @return the Object
       * @exception ServiceException if an error occurs
       */
      public Object lookup( final String role )
          throws ServiceException
      {
          final Object component = m_components.get( role );
  
          if( null != component )
          {
              return component;
          }
          else if( null != m_parent )
          {
              return m_parent.lookup( role );
          }
          else
          {
              throw new ServiceException( "Unable to provide implementation for " + role );
          }
      }
  
      public boolean hasService( final String role ) {
          boolean componentExists = false;
  
          try
          {
              this.release(this.lookup(role));
              componentExists = true;
          }
          catch (Throwable t)
          {
              // Ignore all throwables--we want a yes or no answer.
          }
  
          return componentExists;
      }
  
      /**
       * Place Component into ComponentManager.
       *
       * @param role the components role
       * @param component the component
       */
      public void put( final String role, final Object object )
      {
          checkWriteable();
          m_components.put( role, object );
      }
  
      /**
       * Release component.
       *
       * @param component the component
       */
      public void release( final Object component )
      {
          // if the ServiceManager handled pooling, it would be
          // returned to the pool here.
      }
  
      /**
       * Build a human readable representation of ComponentManager2.
       *
       * @return the description of ComponentManager2
       */
      public String toString()
      {
          final StringBuffer buffer = new StringBuffer();
          final Iterator components = m_components.keySet().iterator();
          buffer.append( "Services:" );
  
          while( components.hasNext() )
          {
              buffer.append( "[" );
              buffer.append( components.next() );
              buffer.append( "]" );
          }
  
          return buffer.toString();
      }
  
      /**
       * Helper method for subclasses to retrieve parent.
       *
       * @return the parent ServiceManager
       */
      protected final ServiceManager getParent()
      {
          return m_parent;
      }
  
      /**
       * Helper method for subclasses to retrieve component map.
       *
       * @return the component map
       */
      protected final Map getComponentMap()
      {
          return m_components;
      }
  
      public void makeReadOnly()
      {
          m_readOnly = true;
      }
  
      protected final void checkWriteable()
          throws IllegalStateException
      {
          if( m_readOnly )
          {
              throw new IllegalStateException( "ServiceManager is read only and can not be
modified" );
          }
      }
  }
  
  
  

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


Mime
View raw message