avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcconn...@apache.org
Subject cvs commit: avalon-sandbox/merlin/merlin-core/src/java/org/apache/avalon/merlin/block/impl StandardBlock.java StandardBlock.xinfo StandardBlockLoader.java DefaultBlock.java DefaultBlock.xinfo DefaultBlockLoader.java
Date Sun, 20 Apr 2003 12:18:06 GMT
mcconnell    2003/04/20 05:18:06

  Added:       merlin/merlin-core/src/java/org/apache/avalon/merlin/block/impl
                        StandardBlock.java StandardBlock.xinfo
                        StandardBlockLoader.java
  Removed:     merlin/merlin-core/src/java/org/apache/avalon/merlin/block/impl
                        DefaultBlock.java DefaultBlock.xinfo
                        DefaultBlockLoader.java
  Log:
  DefaultBlock and DefaultBlockLoader replaced by StandardBlock and StandardBlockLoader.  Change reflects refactoring of classes and the approach used to build the meta-data model. Deployment functionality is expclusively within the block implementation.
  
  Revision  Changes    Path
  1.1                  avalon-sandbox/merlin/merlin-core/src/java/org/apache/avalon/merlin/block/impl/StandardBlock.java
  
  Index: StandardBlock.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 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", "Apache Avalon", "Avalon Framework" 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.avalon.merlin.block.impl;
  
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.avalon.assembly.appliance.Appliance;
  import org.apache.avalon.assembly.appliance.ApplianceContext;
  import org.apache.avalon.assembly.appliance.ApplianceException;
  import org.apache.avalon.assembly.appliance.ApplianceRepository;
  import org.apache.avalon.assembly.appliance.DefaultAppliance;
  import org.apache.avalon.assembly.appliance.DefaultApplianceContext;
  import org.apache.avalon.assembly.appliance.DependencyGraph;
  import org.apache.avalon.assembly.engine.EngineClassLoader;
  import org.apache.avalon.assembly.locator.Locator;
  import org.apache.avalon.assembly.util.ExceptionHelper;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.merlin.block.Block;
  import org.apache.avalon.merlin.block.BlockException;
  import org.apache.avalon.merlin.block.Library;
  import org.apache.avalon.merlin.container.Container;
  import org.apache.avalon.merlin.container.ContainmentProfile;
  import org.apache.avalon.merlin.container.StateEvent;
  import org.apache.avalon.merlin.container.StateListener;
  import org.apache.avalon.meta.info.DependencyDescriptor;
  import org.apache.avalon.meta.info.ServiceDescriptor;
  import org.apache.avalon.meta.model.Profile;
  
  /**
   * The default implementation of a Block.  The implementation provides
   * support for convinence operations related to its role as a containment
   * handler by delegating to the container it is managing.
   */
  public class StandardBlock extends DefaultAppliance implements Block, Runnable, StateListener
  {
      //-------------------------------------------------------------------------------
      // static
      //-------------------------------------------------------------------------------
  
      private static final int DISASSEMBLED = 1000;
      private static final int TERMINATED = 2000;
      private static final int DISPOSED = 3000;
  
      //-------------------------------------------------------------------------------
      // state
      //-------------------------------------------------------------------------------
  
     /**
      * The engine classloader.
      */
      EngineClassLoader m_engine;
  
     /**
      * The root container instance that this block is managing.
      */
      private Container m_container;
  
     /**
      * Flag holding the assembled state of the block.
      */
      private boolean m_assembled = false;
  
      /**
       * The thread in which we will run the container.
       */
      private Thread m_thread;
  
     /**
      * Flag holding the running state of the block.
      */
      private boolean m_running = false;
  
      /**
       * The container is managed as a thread under which the current state
       * is recorded in the m_state state member.
       */
      private int m_state = StateEvent.UNKNOWN;
  
      /**
       * The thread periodically checks for state change requests enter in
       * the m_action state member and attempts to bring the m_state value to
       * be equal to the m_action value and once achieved goes off for a
       * sleep.
       */
      private Integer m_action = new Integer( StateEvent.UNKNOWN );
  
      /**
       * An error raised by the managed container.
       */
      private BlockException m_error;
  
      /**
       * The apliance context.
       */
      private ApplianceContext m_applianceContext;
  
     /**
      * The appliance manager.
      */
      private ApplianceRepository m_repository;
  
     /**
      * List of the subsidiary blocks.
      */
      private List m_blocks = new ArrayList();
  
     /**
      * Map of container objects keyed by block.
      */
      private Map m_containers = new Hashtable();
  
     /**
      * Reference to the set of appliances to be terminated.  The set
      * appliances is based on the shutdown graph resolved during the
      * disassembly phase.
      */
      private Appliance[] m_shutdown;
  
     /**
      * Flag holding the deoplyed state of the block.
      */
      private boolean m_deployed = false;
  
     /**
      * Flag holding the decommissioned state of the block.
      */
      private boolean m_decommissioned = false;
  
     /**
      * Flag holding the disassembled state of the block.
      */
      private boolean m_disassembled = false;
  
     /**
      * Flag holding the terminated state of the block.
      */
      private boolean m_terminated = false;
  
     /**
      * The containment profile.
      */
      private ContainmentProfile m_descriptor;
  
      //=====================================================================
      // Contextualizable
      //=====================================================================
  
     /**
      * Supply a object locator to the instance.
      * @param locator the object locator
      * @exception LocatorException if a object location error occurs
      */
      public void contextualize( Locator context ) throws ContextException
      {
          super.contextualize( context );
          m_applianceContext =
            (ApplianceContext) context.get( "urn:assembly:appliance.context" );
          m_repository =
            (ApplianceRepository) context.get( "urn:assembly:appliance.repository" );
          m_descriptor =
            (ContainmentProfile) context.get( "urn:merlin:container.profile" );
          m_engine = m_descriptor.getEngine();
      }
  
      //=====================================================================
      // Initializable
      //=====================================================================
  
     /**
      * Initialization of the blocks during which appliance instances managed by the blocks
      * will be established.
      *
      * @exception Exception if a block initialization error occurs
      */
      public void initialize() throws Exception
      {
          super.initialize();
          if( m_engine == null )
          {
              throw new IllegalStateException( "context" );
          }
  
          //
          // construct the appliance instances managed by this block
          //
  
          Profile[] profiles = m_descriptor.getComponents();
          for( int i=0; i<profiles.length; i++ )
          {
              Profile profile = profiles[i];
              if( getLogger().isDebugEnabled() )
              {
                  final String message =
                    "adding child profile: " + profile + " in " + this;
                  getLogger().debug( message );
              }
  
              DefaultApplianceContext context =
                 new DefaultApplianceContext( profile );
              context.setPartitionName( getPath() );
              context.setStartupPolicy( false );
              context.makeReadOnly();
  
              m_engine.createAppliance( context, true );
          }
  
          //
          // construct the subcontainers managed by this block
          //
  
          ContainmentProfile[] containers = m_descriptor.getContainers();
          for( int i=0; i<containers.length; i++ )
          {
              ContainmentProfile profile = containers[i];
              if( getLogger().isDebugEnabled() )
              {
                  final String message =
                    "adding child container: " + profile + " in " + this;
                  getLogger().debug( message );
              }
  
              DefaultApplianceContext context =
                 new DefaultApplianceContext( profile );
              context.setApplianceClassname( StandardBlock.class.getName() );
              context.setPartitionName( getPath() );
              context.setStartupPolicy( false );
              context.put( "urn:merlin:container.profile", profile );
              context.makeReadOnly();
  
              try
              {
                  Block block = (Block) 
                    profile.getEngine().createAppliance( context, true );
                  m_blocks.add( block );
              }
              catch( Throwable e )
              {
                  final String error = 
                    "Unable to establish subsidiary block from profile: " 
                    + profile + " in block: " + this;
                  throw new BlockException( error, e );
              }
          }
      }
  
      //-------------------------------------------------------------------------------
      // Appliance
      //-------------------------------------------------------------------------------
  
     /**
      * Get the appliance URL.
      * @return the appliance URL
      */
      public URL getURL()
      {
          return m_repository.getURL();
      }
  
     /**
      * Assemble the appliance.  The implementation extends the default
      * appliance behavior by instantiating the container it is managing,
      * and applying assembly to the container instance. This results in
      * container creating appliance instances for the component is is
      * managing together with assembly of its sub-containers.
      *
      * @exception ApplianceException if an error occurs during appliance assembly
      */
      public void assemble( DependencyGraph graph ) throws ApplianceException
      {
          if( m_assembled )
          {
              return;
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug("block assembly: " + this );
          }
  
          //
          // add the dependency graph to the context that will be used to establish
          // the container so that the container can handle orderly startup and
          // shutdown of components, then assemble the appliances contained within
          // the block
          //
  
          Map context = m_applianceContext.getDeploymentContext();
          context.put( "urn:merlin:container.dependency-graph", graph );
          context.put( "urn:merlin:container.listener", this );
          super.assemble( graph );
  
          //
          // now that we have assembled ourself we can continue with the
          // assembly of the contents of this block
          //
  
          try
          {
              assembleComponents( graph );
          }
          catch( Throwable e )
          {
              final String error =
                "Assembly failure attributable to embedded appliance.";
              throw new ApplianceException( error, e );
          }
  
          //
          // assemble the subsidiary blocks
          //
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
  
              if( getLogger().isDebugEnabled() )
              {
                  final String message =
                    "activating block: " + block;
                  getLogger().debug( message );
              }
  
              try
              {
                  block.assemble( new DependencyGraph( graph ) );
                  Container container = (Container) block.resolve( this );
                  m_containers.put( block, container );
              }
              catch( Throwable e )
              {
                  final String error =
                    "Could not establish a sub-container: "
                    + block
                    + " in block: " + this;
                  throw new ApplianceException( error, e );
              }
          }
  
          if( getLogger().isDebugEnabled() )
          {
              Appliance[] startup = graph.getStartupGraph( );
              StringBuffer buffer = new StringBuffer(
                "startup sequence for " + this + " (" + startup.length + ") " );
              for( int p=0; p<startup.length; p++ )
              {
                  if( p == 0 )
                  {
                      buffer.append( startup[p] );
                  }
                  else
                  {
                      buffer.append( ", " + startup[p] );
                  }
              }
              getLogger().debug( buffer.toString() );
          }
      }
  
     /**
      * Startup the components in this container.
      * @exception Exception if a startup error occurs
      */
      private void assembleComponents( DependencyGraph graph ) throws ApplianceException
      {
          //
          // add all of the children to the graph so that they are available
          // in the dependency resolution process
          //
  
          Appliance[] appliances = getAppliances();
          for( int i=0; i<appliances.length; i++ )
          {
              Appliance appliance = appliances[i];
              if( appliance != this )
              {
                  graph.add( appliance );
              }
          }
  
          //
          // for all of the appliances invoke assembly
          //
  
          for( int i=0; i<appliances.length; i++ )
          {
              Appliance appliance = appliances[i];
              if(( appliance != this ) )
              {
                  appliance.assemble( graph );
              }
          }
      }
  
     /**
      * Return the set of locally managed appliance instances.
      * @return the set of appliance instances local to this block.
      */
      public Appliance[] getAppliances()
      {
          ArrayList list = new ArrayList();
          Appliance[] appliances = m_repository.getAppliances();
          for( int i=0; i<appliances.length; i++ )
          {
              Appliance appliance = appliances[i];
              if( appliance != this )
              {
                  list.add( appliance );
              }
          }
          return (Appliance[]) list.toArray( new Appliance[0] );
      }
  
     /**
      * Disassemble the block.
      */
      public void disassemble()
      {
          if( m_disassembled )
          {
              return;
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "disassemble" );
          }
  
          if( !m_deployed )
          {
              throw new IllegalStateException( "deployment" );
          }
  
          synchronized( m_action )
          {
              m_action = new Integer( StateEvent.STOPPED );
              while( ( m_state < StateEvent.STOPPED  ) && ( m_error == null ) )
              {
                  sleep();
              }
  
              if( m_error != null )
              {
                  if( getLogger().isErrorEnabled() )
                  {
                      final String msg = "Unexpected error during disassembly.";
                      String error = ExceptionHelper.packException( msg, m_error );
                      getLogger().error( error );
                      m_error = null;
                  }
              }
          }
      }
  
     /**
      * Terminate the block.  If a container has been established, the implemetation
      * will relase the container and continue with appliance termination.
      */
      public void terminate()
      {
          if( m_terminated )
          {
              return;
          }
  
          if( !m_deployed )
          {
              handleTermination();
          }
  
          synchronized( m_action )
          {
              m_action = new Integer( TERMINATED );
              while( ( m_state < TERMINATED ) && ( m_error == null ) )
              {
                  sleep();
              }
  
              if( m_error != null )
              {
                  if( getLogger().isErrorEnabled() )
                  {
                      final String msg = "Unexpected error during termination.";
                      String error = ExceptionHelper.packException( msg, m_error );
                      getLogger().error( error );
                      m_error = null;
                  }
              }
          }
      }
  
      //-------------------------------------------------------------------------------
      // Block
      //-------------------------------------------------------------------------------
  
     /**
      * Deploy the block during which appliances managed by the block
      * will be established as executing components.
      *
      * @exception Exception if a deployment error occurs
      */
      public void deploy() throws Exception
      {
          if( getDependencyGraph() == null )
          {
              final String error =
                "Cannot deploy block " + this + " before assembly.";
              throw new IllegalStateException( error );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "deployment" );
          }
  
          //
          // construct and start a thread in which this block will execute
          //
  
          m_thread = new Thread( this, super.getPath() );
          m_thread.setContextClassLoader( m_engine );
          m_thread.start();
  
          synchronized( m_action )
          {
              m_action = new Integer( StateEvent.STARTED );
              while( ( m_state < StateEvent.STARTED ) && ( m_error == null ) )
              {
                  sleep();
              }
  
              if( m_error != null )
              {
                  m_state = StateEvent.STOPPED;
                  final String error =
                    "Unexpected deployment error.";
                  Exception exception = new BlockException( error, m_error );
                  m_error = null;
                  throw exception;
              }
          }
  
          //
          // deploy the subsidiary blocks
          //
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
  
              try
              {
                  block.deploy();
                  Container container = (Container) block.resolve( this );
                  m_containers.put( block, container );
              }
              catch( Throwable e )
              {
                  final String error =
                    "Subsidiary block deployment error in: " + block
                    + " in parent block: " + this;
                  m_error = new BlockException( error, e );
                  break;
              }
          }
  
          m_deployed = true;
      }
  
     /**
      * Decommission the block.
      *
      * @exception Exception if a deployment error occurs
      */
      public void decommission()
      {
          if( !m_deployed )
          {
              throw new IllegalStateException( "deployment" );
          }
  
          synchronized( m_action )
          {
              m_action = new Integer( StateEvent.STOPPED );
              while( ( m_state < StateEvent.STOPPED ) && ( m_error == null ) )
              {
                  sleep();
              }
  
              if( m_error != null )
              {
                  if( getLogger().isErrorEnabled() )
                  {
                      final String msg = "Unexpected error during decommissioning.";
                      String error = ExceptionHelper.packException( msg, m_error );
                      getLogger().error( error );
                  }
                  m_state = StateEvent.STOPPED;
              }
          }
      }
  
      //-------------------------------------------------------------------------------
      // Runnable
      //-------------------------------------------------------------------------------
  
      /**
       * Starts the thread of execution for the block.  This operation is
       * invoked by the container constructor.
       */
      public void run()
      {
          if( !m_running )
          {
              m_running = true;
          }
  
          try
          {
  
              m_container = (Container) resolve( this );
  
              //
              // while desired state of the hosted container is something
              // other than DISPOSED, check if the desired state is different
              // from the current state reported by the container, and if
              // so initiate a container state change
              //
  
              while( m_action.intValue() < DISPOSED )
              {
                  synchronized( m_action )
                  {
                      if( m_state != m_action.intValue() )
                      {
                          switch( m_action.intValue() )
                          {
                              case StateEvent.STARTED:
                                  if( m_state == StateEvent.INITIALIZED )
                                  {
                                      m_container.startup();
                                  }
                                  else if( m_state == StateEvent.SUSPENDED )
                                  {
                                      m_container.resume();
                                  }
                                  break;
                              case StateEvent.SUSPENDED:
                                  if( m_state == StateEvent.STARTED )
                                  {
                                      m_container.suspend();
                                  }
                                  break;
                              case StateEvent.STOPPED:
                                  handleDecommissioning();
                                  break;
                              case DISASSEMBLED:
                                  handleDisassembly();
                                  break;
                              case TERMINATED:
                                  handleTermination();
                                  break;
                          }
                      }
                  }
                  sleep();
              }
  
              getLogger().debug( "exit: " + m_state );
          }
          catch( Throwable e )
          {
              final String error = "Unexpected runtime error in block:" + this;
              m_error = new BlockException( error, e );
          }
      }
  
      private void handleDecommissioning()
      {
          //
          // decommission the subsidiary blocks
          //
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
              block.decommission();
          }
  
          if( m_container != null )
          {
              if( ( m_state == StateEvent.STARTED )
                || ( m_state == StateEvent.SUSPENDED ) )
              {
                  m_container.shutdown();
              }
          }
          else
          {
              m_state = StateEvent.STOPPED;
          }
  
          m_decommissioned = true;
      }
  
      private void handleDisassembly()
      {
          if( !m_decommissioned )
          {
              handleDecommissioning();
          }
  
          m_shutdown = getDependencyGraph().getShutdownGraph();
  
          if( getLogger().isDebugEnabled() )
          {
              StringBuffer buffer = new StringBuffer( "dissassemble: " );
              for( int p=0; p<m_shutdown.length; p++ )
              {
                 buffer.append( ", " + m_shutdown[p] );
              }
              getLogger().debug( buffer.toString() );
          }
  
          for( int i=0; i<m_shutdown.length; i++ )
          {
              Appliance appliance = m_shutdown[i];
              try
              {
                  appliance.disassemble();
              }
              catch( Throwable e )
              {
                  final String warning =
                    "ignoring dissassembly error from appliance: " + appliance
                    + " (" + e.toString() + ")";
                  getLogger().warn( warning );
              }
          }
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
              try
              {
                  block.disassemble();
              }
              catch( Throwable e )
              {
                  final String warning =
                    "ignoring dissassembly error from block: " + block
                    + " (" + e.toString() + ")";
                  getLogger().warn( warning );
              }
          }
  
          super.disassemble();
          m_disassembled = true;
          m_state = DISASSEMBLED;
      }
  
      private void handleTermination()
      {
          if( m_terminated )
          {
              return;
          }
  
          if( !m_disassembled )
          {
              handleDisassembly();
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "termination" );
          }
  
          for( int i=0; i<m_shutdown.length; i++ )
          {
              Appliance appliance = m_shutdown[i];
              appliance.terminate();
          }
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
              block.terminate();
          }
  
          m_terminated = true;
          m_state = TERMINATED;
          super.terminate();
  
          //
          // trigger termination of the thread
          //
  
          m_action = new Integer( DISPOSED );
      }
  
      //-------------------------------------------------------------------------------
      // internal
      //-------------------------------------------------------------------------------
  
      /**
       * Method invoked when a container state changes.
       * @param event the state event
       */
      public void stateChanged( StateEvent event )
      {
          if( event.getError() != null )
          {
              if( getLogger().isErrorEnabled() )
              {
                  final String error =
                    ExceptionHelper.packException(
                      "Runtime containment error in: "
                      + this, event.getError() );
                  getLogger().error( error );
              }
          }
          else
          {
              if( getLogger().isDebugEnabled() )
              {
                  getLogger().debug("state event: " + event );
              }
          }
          m_state = event.getState();
      }
  
      /**
       * Internal utility to sleep a bit.
       */
      private void sleep()
      {
          try
          {
              Thread.sleep( 100 );
          }
          catch( Throwable wakeup )
          {
              // return
          }
      }
  
      public String toString()
      {
          return "[block:/" + getURL().getPath() + "]";
      }
  }
  
  
  
  1.1                  avalon-sandbox/merlin/merlin-core/src/java/org/apache/avalon/merlin/block/impl/StandardBlock.xinfo
  
  Index: StandardBlock.xinfo
  ===================================================================
  <?xml version="1.0"?>
  <!DOCTYPE type
        PUBLIC "-//AVALON/Component Type DTD Version 1.0//EN"
               "http://avalon.apache.org/dtds/meta/type_1_1.dtd" >
  
  <!--  
  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.
  
  @author  Avalon Development Team
  @version 1.0 12/03/2001
  -->
  
  <type>
  
    <info>
      <name>block</name>
    </info>
  
    <context>
  
      <attributes>
        <attribute key="urn:assembly:lifecycle.context.strategy"
            value="org.apache.avalon.assembly.locator.Contextualizable"/>
      </attributes>
  
      <entry key="urn:assembly:engine" 
         type="org.apache.avalon.assembly.engine.EngineClassLoader"/>
      <entry key="urn:assembly:lifestyle.service" 
         type="org.apache.avalon.assembly.lifestyle.LifestyleService"/>
      <entry key="urn:assembly:threads.manager" 
         type="org.apache.excalibur.mpool.PoolManager"/>
      <entry key="urn:assembly:appliance.system" 
         type="org.apache.avalon.assembly.locator.Locator"/>
      <entry key="urn:assembly:appliance.context" 
         type="org.apache.avalon.assembly.appliance.ApplianceContext"/>
      <entry key="urn:assembly:appliance.repository" 
         type="org.apache.avalon.assembly.appliance.ApplianceRepository"/>
      <entry key="urn:merlin:container.profile" 
         type="org.apache.avalon.merlin.container.ContainmentProfile"/>
  
    </context>
  
    <services>
      <service type="org.apache.avalon.merlin.block.Block"/>
    </services>
  
  </type>
  
  
  
  
  1.1                  avalon-sandbox/merlin/merlin-core/src/java/org/apache/avalon/merlin/block/impl/StandardBlockLoader.java
  
  Index: StandardBlockLoader.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 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", "Apache Avalon", "Avalon Framework" 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.avalon.merlin.block.impl;
  
  import java.io.File;
  import java.io.InputStream;
  import java.net.JarURLConnection;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.List;
  import java.util.Map;
  import java.util.Properties;
  import java.util.jar.JarFile;
  import java.util.zip.ZipEntry;
  
  import org.apache.avalon.assembly.logging.LoggingManager;
  import org.apache.avalon.assembly.appliance.DefaultApplianceContext;
  import org.apache.avalon.assembly.engine.EngineClassLoader;
  import org.apache.avalon.assembly.engine.EngineException;
  import org.apache.avalon.assembly.engine.model.Classpath;
  import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
  import org.apache.avalon.assembly.engine.model.DefaultClasspath;
  import org.apache.avalon.assembly.engine.model.LibraryDescriptor;
  import org.apache.avalon.assembly.engine.type.UnknownTypeException;
  import org.apache.avalon.assembly.locator.Contextualizable;
  import org.apache.avalon.assembly.locator.DefaultLocator;
  import org.apache.avalon.assembly.locator.Locator;
  import org.apache.avalon.framework.Version;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  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.configuration.DefaultConfigurationBuilder;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.merlin.block.Block;
  import org.apache.avalon.merlin.block.BlockException;
  import org.apache.avalon.merlin.block.BlockLoader;
  import org.apache.avalon.merlin.block.BlockRuntimeException;
  import org.apache.avalon.merlin.block.Library;
  import org.apache.avalon.merlin.container.Container;
  import org.apache.avalon.merlin.container.Target;
  import org.apache.avalon.merlin.container.Targets;
  import org.apache.avalon.merlin.container.ContainerException;
  import org.apache.avalon.merlin.container.ContainmentProfile;
  import org.apache.avalon.merlin.container.builder.XMLContainerCreator;
  import org.apache.avalon.merlin.container.impl.DefaultContainer;
  import org.apache.avalon.meta.info.DependencyDescriptor;
  import org.apache.avalon.meta.info.InfoDescriptor;
  import org.apache.avalon.meta.info.ServiceDescriptor;
  import org.apache.avalon.meta.info.Type;
  import org.apache.avalon.meta.info.builder.XMLTypeCreator;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.avalon.meta.model.builder.XMLProfileCreator;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  import org.apache.excalibur.mpool.PoolManager;
  
  
  /**
   * Implementation of the block loader.
   *
   * <ul>
   * <li>loading kernel.xml configuration
   * <li>loading blocks.xml configuration
   * <li>establishment of the logging system
   * <li>loading internal jar-file dependencies
   * <li>establishment of a root component management engine
   * <li>block abstraction that encapsulates a heirachical container model
   * <li>block configuration repository
   * <li>block assembly, deployment and decommissioning
   * <li>management of interupt conditions and kernel disposal
   * <li>error management
   * </ul>
   *
   * WARNING: This class is in the process of refactoring.
   *
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2003/04/20 12:18:06 $
   * @see StandardBlock
   */
  
  public class StandardBlockLoader extends AbstractLogEnabled implements Contextualizable, Initializable, Disposable, BlockLoader
  {
      //==============================================================
      // static
      //==============================================================
  
      protected static final String BLOCK_XML_ENTRY = "BLOCK-INF/block.xml";
  
      protected static final XMLContainerCreator CREATOR = new XMLContainerCreator();
  
      private static final XMLProfileCreator BUILDER = new XMLProfileCreator();
  
      private static final XMLTypeCreator TYPE_CREATOR = new XMLTypeCreator();
  
      //==============================================================
      // state
      //==============================================================
  
     /**
      * The application home directory.
      */
      private File m_root;
  
     /**
      * The home directory.
      */
      private File m_home;
  
     /**
      * Configuration fragments keyed by appliance path.
      */
      private final Map m_library = new Hashtable();
  
      /**
       * The logging manager.
       */
      private LoggingManager m_logging;
  
      /**
       * The pool manager.
       */
      private PoolManager m_pool;
  
      /**
       * The parent classloader.
       */
      private ClassLoader m_system;
  
      /**
       * The common classloader.
       */
      private ClassLoader m_common;
  
      /**
       * The domain
       */
      private String m_domain;
  
      //==============================================================
      // Contextualizable
      //==============================================================
  
     /**
      * Contextualization of the block loader.
      */
      public void contextualize( Locator context ) throws ContextException
      {
          m_root = (File) context.get( "urn:assembly:system" );
          m_home = (File) context.get( "urn:merlin:home" );
          m_logging = (LoggingManager) context.get( "urn:merlin:logging-manager" );
          m_pool = (PoolManager) context.get( "urn:merlin:pool-manager" );
          m_system = (ClassLoader) context.get( "urn:merlin:classloader.system" );
          m_common = (ClassLoader) context.get( "urn:merlin:classloader.common" );
          m_domain = (String) context.get( "urn:merlin:domain" );
      }
  
      //==============================================================
      // Initializable
      //==============================================================
  
      public void initialize() throws Exception
      {
          if( m_root == null )
          {
              throw new IllegalStateException( "contextualization" );
          }
      }
  
      //==============================================================
      // Disposable
      //==============================================================
  
     /**
      * Disposal of the loader and related resources.
      */
      public void dispose()
      {
      }
  
      //==============================================================
      // BlockLoader
      //==============================================================
  
     /**
      * Load a block declared in the supplied block and configuration URL.
      * The path URL may refer to a XML file containing a block directive
      * or a jar file containing a block.xml file.
      *
      * @param path the block defintion URL
      * @param overrides the URL to a configuration containing configuration overrides
      * @return the block
      */
      public Block install( final URL path, final URL overrides )
        throws BlockException
      {
          //
          // establish a URL referencing the base directory
          //
  
          URL base = getBasePath( path );
  
          //
          // resolve the source configurations
          //
  
          Configuration block = getSourceConfiguration( path );
          Targets targets = CREATOR.createTargets( getTargetsConfiguration( overrides ) );
  
          //
          // before creating a block we need to build a classloader
          // because the block implementation class may be part of 
          // the block defintion
          //
  
          Configuration implementation = getImplementationFragment( block );
  
          //
          // create the block logical dependencies (as distinct from the
          // physical dependencies of the type managed by the block)
          //
  
          DependencyDescriptor[] dependencies = 
            getBlockLogicalDependencies( block.getChild( "dependencies" ) );
  
          //
          // create the logical block services
          //
  
          ServiceDescriptor[] services = 
            getBlockLogicalServices( block.getChild( "services" ) );
  
          //
          // create the engine
          //
  
          EngineClassLoader engine = 
            createEngine( implementation.getChild( "engine" ), path );
  
          //
          // create the containment type
          //
  
          final String classname =
            implementation.getAttribute( "class", DefaultContainer.class.getName() );
  
          Type type = null;
          try
          {
              type = engine.getRepository().getTypeManager().getType( classname );
          }
          catch( UnknownTypeException ute )
          {
              final String error =
                "Container definition references an unknown type: " + classname;
              throw new BlockException( error );
          }
          catch( Throwable e )
          {
              final String error =
                "Internal error while resolving root container type: " + classname
                + " using class: " + classname;
              throw new BlockException( error, e );
          }
  
          //
          // create the containment profile
          //
  
          ContainmentProfile profile = null;
          try
          {
              profile = CREATOR.createContainmentProfile( 
                base, engine, type, services, dependencies, 
                implementation, targets, Container.PATH_SEPERATOR );
          }
          catch( Throwable e )
          {
              final String error =
                "Unable to create root containment profile.";
              throw new BlockException( error, e );
          }
  
          //
          // create the block
          //
  
          return createBlock( profile, Container.PATH_SEPERATOR );
      }
  
     /**
      * Creation of the root engine.
      *
      * @param config the engine configuration from which extension paths and
      *    classpath declarations are resolved
      * @param url the base url
      * @return the engine
      */
      private EngineClassLoader createEngine( Configuration config, URL url )
        throws BlockException
      {
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "creating engine" );
          }
  
          Configuration lib = config.getChild( "library", false );
  
          Classpath classpath = null;
          Configuration classpathConfig = config.getChild( "classpath", false );
          if( classpathConfig != null )
          {
              try
              {
                  ClasspathDescriptor descriptor = 
                    CREATOR.createClasspathDescriptor( classpathConfig );
                  classpath = new DefaultClasspath( descriptor );
              }
              catch( Throwable e )
              {
                  final String error =
                   "Cannot construct root container classpath.";
                  throw new BlockException( error, e );
              }
          }
  
          try
          {
              EngineClassLoader engine =
                new EngineClassLoader( new URL[]{ getBasePath( url ) }, m_system );
  
              engine.enableLogging( getLogger() );
  
              DefaultLocator context = new DefaultLocator();
              context.put( "urn:merlin:domain", m_domain );
              context.put( "urn:assembly:home", m_home );
              context.put( "urn:assembly:system", m_root );
              context.put( "urn:assembly:engine.bootstrap", "true" );
              context.put( LoggingManager.KEY, m_logging );
              context.put( "urn:assembly:threads.manager", m_pool );
              if( lib != null )
              {
                  LibraryDescriptor extensions =
                    CREATOR.createLibraryDescriptor( config.getChild( "library" ) );
                  context.put( "urn:assembly:engine.extensions", extensions );
              }
              if( classpath != null )
              {
                  context.put( "urn:assembly:engine.classpath", classpath );
              }
              context.makeReadOnly();
              engine.contextualize( context );
              engine.initialize();
  
              //
              // make sure that the merlin internal components are registered
              // (problem occurs when running under a junit test where the
              // classloader does not expose the loaded jar files)
              //
  
              try
              {
                  engine.register(
                    "org.apache.avalon.assembly.lifecycle.context.DefaultContextualizer" );
                  engine.register(
                    "org.apache.avalon.assembly.lifecycle.context.AvalonContextualizer" );
                  engine.register(
                    "org.apache.avalon.merlin.container.impl.DefaultContainer" );
                  engine.register(
                    "org.apache.avalon.merlin.block.impl.StandardBlock" );
              }
              catch( Throwable e )
              {
                  // already registered
              }
  
              return engine;
          }
          catch( Throwable e )
          {
              final String error = "Engine bootstrap failure.";
               throw new BlockException( error, e );
          }
      }
  
      //==============================================================
      // internals
      //==============================================================
  
     /**
      * Read in the configuration file containing the customize configuration targets.
      * @param url the url to the targets configuration file (normally config.xml)
      * @return the configuration containing the targets
      */
      private Configuration getTargetsConfiguration( final URL url ) throws BlockException
      {
          if( url == null )
          {
              return new DefaultConfiguration( 
                "targets", StandardBlockLoader.class.getName() );
          }
          return createConfiguration( url.toString() );
      }
  
  
     /**
      * The supplied URL is normally either a block.xml file URL or a jar url.
      * If it is a jar url then simply return it but it is isn't then return
      * the equivalent of the URL parent directory.
      * @param url the URL to resolve a base path from
      * @return the base URL
      */
      public static URL getBasePath( final URL url )
      {
          if( url.getProtocol().equals( "jar" ) )
          {
              return url;
          }
          else
          {
              // its a block.xml file so we need to return the url with the
              // filename stripped off it
              try
              {
                  final String path = url.getPath();
                  final String base = path.substring( 0, ( path.lastIndexOf("/") + 1 ) );
                  return new URL( url, base );
              }
              catch( Throwable e )
              {
                  final String error =
                    "Unexpected error while resolving base path from URL: " + url;
                  throw new BlockRuntimeException( error, e );
              }
          }
      }
  
     /**
      * Internal utilitity to read in a configuration from a uri.
      * @param uri the uri to the configuration source
      * @return the configuration object
      */
      private Configuration createConfiguration( final String uri ) throws BlockException
      {
          DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
          try
          {
              return builder.build( uri );
          }
          catch( Throwable e )
          {
              final String error =
                "Unable to create configuration from source: " + uri;
              throw new BlockException( error, e );
          }
      }
  
      private Configuration getSourceConfiguration( final URL url ) throws BlockException
      {
          String uri = url.toString();
          if( url.getProtocol().equals( "jar" ) )
          {
              try
              {
                  JarFile jar = getJarFile( url );
                  return getSourceConfiguration( jar );
              }
              catch( Throwable e )
              {
                  final String error =
                    "Unable to resolve packaged block description on path: " + url;
                  throw new BlockException( error, e );
              }
          }
          else
          {
              // its either a simulated block or include
  
              try
              {
                  return createConfiguration( uri );
              }
              catch( Throwable e )
              {
                  try
                  {
                      return createConfiguration( uri + "BLOCK-INF/block.xml" );
                  }
                  catch( Throwable ce )
                  {
                      final String error =
                        "Unable to resolve block description on path: " + uri;
                      throw new BlockException( error, e );
                  }
              }
          }
      }
  
     /**
      * Create a block.
      *
      * @param descriptor the container descriptor
      * @param partition the partition to assign to the container
      * @return the block
      * @exception BlockException if an error occurs during creation of the block
      */
      private Block createBlock(
        final ContainmentProfile profile, final String partition )
        throws BlockException
      {
          //
          // create the appliance context for the container - the map
          // contains the context entries that will be provided to the
          // container (supplimented by entries added by the block
          // implementation) and the context object is the context
          // to be applied to the block.
          //
  
          final DefaultApplianceContext context = 
            new DefaultApplianceContext( profile );
  
          context.setName( "/" );
          context.setPartitionName( "/" );
          context.setApplianceClassname( StandardBlock.class.getName() );
          context.put("urn:merlin:container.profile", profile );
          context.makeReadOnly();
  
          //
          // create the containment appliance
          //
  
          try
          {
              Block result = (Block) profile.getEngine().createAppliance( context, true );
              return result;
          }
          catch( Throwable e )
          {
              final String error =
                "Unable to create block: " + partition;
              throw new BlockException( error, e );
          }
      }
  
     /**
      * Return the configuration fragment holding the implementation defintion.
      * This method checks for a child component named 'implementation' and if it exists
      * then the child is returned, otherwise, do the old method of checking for a
      * root container and return that.  If neaither of the above work, throw a exception.
      *
      * @param config the block confiugration
      * @return the implementation configuration fragment
      * @exception BlockException of the implementation fragment cannot be resolved
      */
      private Configuration getImplementationFragment( Configuration config ) throws BlockException
      {
          Configuration imp = config.getChild( "implementation", false );
          if( imp != null )
          {
              return imp;
          }
          imp = config.getChild( "container", false );
          if( imp != null )
          {
              final String error =
                "Block contains a depricated reference to 'container'. \n"
                + "Please replace the root 'container' declaration with 'imlementation'.";
              getLogger().warn( error );
              return imp;
          }
          final String error =
            "Supplied block does not contain an 'implementation' element.\n"
            + ConfigurationUtil.list( config );
          throw new BlockException( error );
      }
  
     /**
      * Create a block info descriptor holding the block name, version and
      * optional properties.
      *
      * @param info the &lt;info&gt; configuration fragment
      * @return the block info descriptor
      */
      private InfoDescriptor createBlockInfoDescriptor( Configuration info )
        throws BlockException
      {
          final String name = info.getChild( "name" ).getValue( null );
          if( name == null )
          {
              final String error =
                "Block " + this + " does not contain a name.";
              getLogger().warn( error );
              return createBlockInfoDescriptor( "unknown", info );
          }
          return createBlockInfoDescriptor( name, info );
      }
  
     /**
      * Create a block info descriptor holding the block name, version and
      * optional properties.
      *
      * @param name the name to assign to the block
      * @param info the &lt;info&gt; configuration fragment
      * @return the block info descriptor
      */
      private InfoDescriptor createBlockInfoDescriptor( String name, Configuration info )
        throws BlockException
      {
          try
          {
              final String classname = StandardBlock.class.getName();
              final Version version =
                Version.getVersion( info.getChild( "version" ).getValue( "1.0" ) );
              final Properties attributes =
                TYPE_CREATOR.buildAttributes( info.getChild( "attributes" ) );
              return new InfoDescriptor( name, classname, version, attributes );
          }
          catch( ConfigurationException ce )
          {
              final String error =
                "Unexpected error building block info desciptor: "
                + name + "\n"
                + ConfigurationUtil.list( info );
              throw new BlockException( error, ce );
          }
      }
  
     /**
      * Resolve the logical dependencies declared by this block.
      * @param config the dependecies configuration fragment
      * @return the set of declared depedency descriptors
      */
      private DependencyDescriptor[] getBlockLogicalDependencies( Configuration config )
        throws BlockException
      {
          try
          {
              return TYPE_CREATOR.buildDependencies( config );
          }
          catch( ConfigurationException ce )
          {
              final String error =
                "Invalid dependencies declaration in block specification:\n"
                 + ConfigurationUtil.list( config );
              throw new BlockException( error, ce );
          }
      }
  
     /**
      * Resolve the logical services declared by this block.
      * @param config the dependecies configuration fragment
      * @return the set of declared depedency descriptors
      */
      private ServiceDescriptor[] getBlockLogicalServices( Configuration config )
        throws BlockException
      {
          try
          {
              return TYPE_CREATOR.buildServices( config );
          }
          catch( ConfigurationException ce )
          {
              final String error =
                "Invalid services declaration in block specification:\n"
                 + ConfigurationUtil.list( config );
              throw new BlockException( error, ce );
          }
      }
  
      private void captureConfigurationTargets( String path, Configuration config )
        throws BlockException
      {
          Configuration[] targets = config.getChildren( "target" );
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug("target override count: " + targets.length );
          }
  
          for( int j=0; j<targets.length; j++ )
          {
              Configuration target = targets[j];
              
              try
              {
                  String name = target.getAttribute( "name" );
                  if( name.startsWith( "/" ) )
                  {
                      name = name.substring( 1 );
                  }
                  String key;
                  if( path.endsWith( "/" ) )
                  {
                      key = path + name;
                  }
                  else
                  {
                      key = path + "/" + name;
                  }
                  m_library.put( key, target.getChild( "configuration" ) );
                  getLogger().debug( "registering configuration for key: " + key );
              }
              catch( Throwable e )
              {
                  final String error =
                    "A configuration target does not declare a name in: "
                    + path
                    + ConfigurationUtil.list( target );
                  throw new BlockException( error, e );
              }
          }
      }
  
  
      private JarFile getJarFile( URL url ) throws MalformedURLException
      {
          URL xurl;
  
          String protocol = url.getProtocol();
          if( protocol.equals("jar") )
          {
              xurl = url;
          }
          else
          {
              xurl = new URL( "jar:" + url.toString() + "!/" );
          }
  
          try
          {
              JarURLConnection connection = 
                (JarURLConnection) xurl.openConnection();
              return connection.getJarFile();
          }
          catch( Throwable ioe )
          {
              final String error =
                "Unexpected Exception while reading jar file from url: " 
                + xurl + " cause: " + ioe;
              throw new RuntimeException( error );
          }
      }
  
      private Configuration getSourceConfiguration( JarFile jar ) 
        throws Exception
      {
          if( jar == null )
          {
              throw new NullPointerException( "jar" );
          }
  
          ZipEntry entry = jar.getEntry( BLOCK_XML_ENTRY );
          if( entry == null )
          {
              final String error =
                "Missing block descriptor: /" 
                + BLOCK_XML_ENTRY;
              throw new BlockException( error );
          }
  
          try
          {
              DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
              InputStream is = jar.getInputStream( entry );
              if( is == null )
              {
                  throw new RuntimeException(
                    "Could not load the configuration resource \"" 
                    + jar.getName() + "\"" );
              }
              return builder.build( is );
          }
          catch( Throwable e )
          {
              final String error = 
                "Unable to create configuration from jar file: " 
                + jar.getName();
              throw new BlockException( error, e );
          }
      }
  
      protected Profile createProfile( 
        String name, EngineClassLoader engine, Configuration config )
        throws ContainerException
      {
          String classname;
          try
          {
              classname = config.getAttribute( "class" );
          }
          catch( Throwable e )
          {
              final String error =
                "Block directive: '" + name 
                + "' contains a component profile without a 'class' attribute.";
              throw new ContainerException( error, e );
          }
  
          Type type;
          try
          {
              type = engine.getRepository().getTypeManager().getType( classname );
          }
          catch( Throwable e )
          {
              final String error =
                "Block directive: '" + name 
                + "' references an unknown component type: "
                + classname;
              throw new ContainerException( error, e );
          }
  
          try
          {
              Profile profile = BUILDER.createProfile( type, config );
              boolean policy = getActivationPolicy( config );
              profile.setActivationPolicy( policy );
              return profile;
          }
          catch( Throwable e )
          {
              final String error =
                "Block directive: '" + name
                + " contains a problamatic profile: "
                + classname;
              throw new ContainerException( error, e );
          }
      }
  
     /**
      * Get the activation policy from a configuration. If no activation attribute
      * is present the value return defaults to FALSE (i.e. activation is deferred).
      *
      * @param config a configuration fragment holding a activation attribute
      * @return TRUE is the value of the activation attribute is 'true' or 'startup'
      *   otherwise the return value is FALSE
      */
      private boolean getActivationPolicy( Configuration config )
      {
          final String value = config.getAttribute( "activation", null );
          if( value == null )
          {
              return false;
          }
          final String string = value.toLowerCase().trim();
          if( string.equals( "startup" ) )
          {
              return true;
          }
          return string.equals( "true" );
      }
  
     /**
      * Utility that handles the creation of a extension set descriptor from
      * a configuration fragment.
      * @param config the configuration
      * @return the library descriptor of null if the supplied configuration is null
      * @exception EngineException if an error occurs
      */
      private LibraryDescriptor createLibraryDescriptor( Configuration config )
        throws EngineException
      {
          if( config == null )
          {
              return null;
          }
          try
          {
              return CREATOR.createLibraryDescriptor( config );
          }
          catch( Throwable e )
          {
              final String error = "Bad library descriptor in configuration: \n"
                + ConfigurationUtil.list( config );
              throw new EngineException( error, e );
          }
      }
  
     /**
      * Utility that handles the creation of a classpath descriptor from
      * a configuration fragment.
      * @param config the configuration
      * @return the classpath descriptor
      * @exception EngineException if an error occurs
      */
      private ClasspathDescriptor createClasspathDescriptor( Configuration config )
        throws EngineException
      {
          try
          {
              return CREATOR.createClasspathDescriptor( config );
          }
          catch( Throwable e )
          {
              final String error = "Bad classpath descriptor: \n"
                + ConfigurationUtil.list( config );
              throw new EngineException( error, e );
          }
      }
  }
  
  
  

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


Mime
View raw message