You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2003/01/19 16:53:56 UTC

cvs commit: avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl DefaultKernel.java DefaultKernel.xinfo KernelLoader.java Resources.properties package.html

mcconnell    2003/01/19 07:53:56

  Added:       merlin/src/java/org/apache/avalon/merlin/container/impl
                        DefaultContainer.java DefaultContainer.xinfo
                        package.html
               merlin/src/java/org/apache/avalon/merlin/kernel/impl
                        DefaultKernel.java DefaultKernel.xinfo
                        KernelLoader.java Resources.properties package.html
  Removed:     merlin/src/java/org/apache/avalon/merlin/container
                        DefaultContainer.java DefaultContainer.xinfo
               merlin/src/java/org/apache/avalon/merlin/kernel
                        DefaultKernel.java DefaultKernel.xinfo
                        KernelLoader.java Resources.properties
  Log:
  A little repackaging to get interface/impl seperation in place.
  
  Revision  Changes    Path
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/impl/DefaultContainer.java
  
  Index: DefaultContainer.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", 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 (INCLUDING, 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.container.impl;
  
  import java.util.List;
  import java.util.Iterator;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.Hashtable;
  
  import org.apache.avalon.assembly.engine.EngineClassLoader;
  import org.apache.avalon.assembly.appliance.Appliance;
  import org.apache.avalon.assembly.appliance.ApplianceContext;
  import org.apache.avalon.assembly.appliance.DefaultApplianceContext;
  import org.apache.avalon.assembly.appliance.ApplianceException;
  import org.apache.avalon.assembly.appliance.DependencyGraph;
  import org.apache.avalon.assembly.lifecycle.AssemblyException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.context.ContextException;
  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.merlin.container.Container;
  import org.apache.avalon.merlin.container.ContainerException;
  import org.apache.avalon.merlin.container.ContainerDescriptor;
  import org.apache.avalon.merlin.container.StateEvent;
  import org.apache.avalon.merlin.container.StateListener;
  import org.apache.avalon.merlin.service.Registry;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  
  /**
   * <p>Default implementation of a container model within which a set 
   * of components and subsidiary containers are managed.</p>
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2003/01/19 15:53:55 $
   */
  public class DefaultContainer extends AbstractLogEnabled 
    implements Container, Contextualizable, Initializable, Disposable
  {
      //==============================================================
      // state
      //==============================================================
  
      private DependencyGraph m_graph;
  
      private ContainerDescriptor m_descriptor;
  
     /**
      * Map of components keyed by appliance.
      */
      private Map m_components = new Hashtable();
  
     /**
      * State event listener list.
      */
      private List m_listeners = new ArrayList();
  
      /**
       * 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;
  
      /**
       * Flag holding the disposed state of the container.
       */
      private boolean m_disposed = false;
  
      //==============================================================
      // Contextualizable
      //==============================================================
  
     /**
      * <p>Application of a runtime context for this container.
      * @param context the runtime context
      */
      public void contextualize( Context context ) throws ContextException
      {
          m_descriptor = (ContainerDescriptor) context.get( "urn:merlin:container.descriptor" );
          m_graph = (DependencyGraph) context.get( "urn:merlin:container.dependency-graph" );
          addStateListener( (StateListener) context.get( "urn:merlin:container.listener" ) ); 
      }
  
      //==============================================================
      // Initializable
      //==============================================================
  
     /**
      * Initialization of the container.  The implememtation uses the intilization
      * phase to verify correct setup including validation of logging channel assignment
      * and container context.
      * @exception IllegalStateException if the logging or context phases have not been
      *   applied 
      */
      public void initialize() throws IllegalStateException
      {
          if( getLogger() == null )
          {
              throw new IllegalStateException("logging");
          }
  
          if( m_graph == null )
          {
              throw new IllegalStateException("context");
          }
  
          //
          // issue an initialization event back to the block
          //
  
          m_state = StateEvent.INITIALIZED;
          fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.INITIALIZED ) );
      }
  
     /**
      * Startup the components in this container.
      * @exception Exception if a startup error occurs
      */
      public void startup() throws Exception
      {
          if( m_state < StateEvent.INITIALIZED )
          {
              throw new IllegalStateException(
                  "Container has not been initialized." );
          }
  
          if( m_state == StateEvent.STARTED )
          {
              return;
          }
  
          if( m_state == StateEvent.STOPPED )
          {
              final String error = "Cannot restart a stopped container.";
              throw new IllegalStateException( error );
          }
  
          try
          {
              startupComponents();
              m_state = StateEvent.STARTED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STARTED ) );
          }
          catch( Throwable e )
          {
              m_state = StateEvent.STOPPED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STOPPED, e ) );
          }
      }
  
      /**
       * Request for the container to suspend all subsidiary containers
       * and all contained components.
       */
      public void suspend()
      {
          if( m_state < StateEvent.INITIALIZED )
          {
              throw new IllegalStateException(
                  "Container has not been initialized." );
          }
  
          if( m_state == StateEvent.SUSPENDED )
          {
              return;
          }
  
          if( m_state > StateEvent.STOPPED )
          {
              throw new IllegalStateException(
                  "Container has been stopped." );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "container suspension" );
          }
  
          try
          {
              suspendComponents();
              m_state = StateEvent.SUSPENDED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.SUSPENDED ) );
          }
          catch( Throwable e )
          {
              m_state = StateEvent.STOPPED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STOPPED, e ) );
          }
      }
  
      /**
       * Request for the container to resume all subsidiary containers
       * and all contained components.
       */
      public void resume() 
      {
          if( m_state != StateEvent.SUSPENDED )
          {
              throw new IllegalStateException(
                  "Container is not suspended." );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "container resuming" );
          }
  
          //
          // resume subsidiary containers
          //
  
          try
          {
              resumeComponents();
              m_state = StateEvent.STARTED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STARTED ) );
          }
          catch( Throwable e )
          {
              m_state = StateEvent.STOPPED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STOPPED, e ) );
          }
      }
  
  
     /**
      * Shutdown all subsidiary containers and all components in this container.
      * @exception Exception if a shutdown error occurs
      */
      public void shutdown()
      {
          if( m_state < StateEvent.STARTED )
          {
              return;
          }
  
          if( m_state == StateEvent.STOPPED )
          {
              return;
          }
  
          if( m_state > StateEvent.STOPPED )
          {
              throw new IllegalStateException( "Already stopped." );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "shutdown" );
          }
  
          //
          // shutdown all of the nested containers before stopping
          // the components in this container
          //
  
          try
          {
              shutdownComponents();
              m_state = StateEvent.STARTED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STOPPED ) );
          }
          catch( Throwable e )
          {
              m_state = StateEvent.STOPPED;
              fireStateChange( new StateEvent( this, m_descriptor.getName(), StateEvent.STOPPED, e ) );
          }
      }
  
     /**
      * Disposal of the container.
      */
      public void dispose()
      {
          if( m_disposed )
          {
              return;
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "disposal" );
          }
  
          m_descriptor = null;
          m_components.clear();
          m_components = null;
          m_disposed = true;
      }
  
     /**
      * Startup the components in this container.
      * @exception Exception if a startup error occurs
      */
      private void startupComponents() throws Exception
      {
          Appliance[] appliances = m_graph.getStartupGraph();
  
          if( getLogger().isDebugEnabled() )
          {
              if( appliances.length > 0 )
              {
                  StringBuffer buffer = new StringBuffer( "startup: " );
                  for( int p=0; p<appliances.length; p++ )
                  {
                      if( p == 0 )
                      {
                          buffer.append( appliances[p] );
                      }
                      else
                      {
                          buffer.append( ", " + appliances[p] );
                      }
                  }
                  getLogger().debug( buffer.toString() );
              }
              else
              {
                  getLogger().debug( "startup" );
              }
          }
  
          for( int i=0; i<appliances.length; i++ )
          {
              Appliance appliance = appliances[i];
              if( appliance.getActivationPolicy() )
              {
                  if( getLogger().isDebugEnabled() )
                  {
                      final String message =
                        "activating component: [" + appliance.getName() + "]"; 
                      getLogger().debug( message );
                  }
                  try
                  {
                      Object object = appliance.resolve( this );
                      m_components.put( appliance, object );
                      if( !appliance.getStartupPolicy() )
                      {
                          if( object instanceof Startable )
                          {
                              try
                              {
                                  ((Startable)object).start();
                              }
                              catch( Throwable e )
                              {
                                  final String error =
                                    "Error during startup of a componet: " + appliance;
                                  throw new ContainerException( error, e );
                              }
                          }
                      }
                  }
                  catch( Throwable e )
                  {
                      final String error =
                        "Could not establish a component: " 
                           + appliance.getName() 
                           + " in container: " + this;
                      throw new ContainerException( error, e );
                  }
              }
          }
      }
  
     /**
      * Startup the components in this container.
      * @exception Exception if a startup error occurs
      */
      private void suspendComponents()
      {
          // not implemented - more thinking needed about the 
          // concepts of deployment strategies
      }
  
     /**
      * Startup the components in this container.
      * @exception Exception if a startup error occurs
      */
      private void resumeComponents()
      {
          // not implemented - more thinking needed about the 
          // concepts of deployment strategies
      }
  
     /**
      * Shutdown all subsidiary containers and all components in this container.
      * @exception Exception if a shutdown error occurs
      */
      private void shutdownComponents() throws Exception
      {
          if( m_graph == null )
          {
              throw new IllegalStateException( "Container has not been contextualized: " + this );
          }
  
          Appliance[] appliances = m_graph.getShutdownGraph();
          for( int i=0; i<appliances.length; i++ )
          {
              Appliance appliance = appliances[i];
              if( !appliance.getStartupPolicy() )
              {
                  // container is handling shutdown
  
                  Object object = m_components.get( appliance );
                  if( object != null )
                  {
                      if( object instanceof Startable )
                      {
                          if( getLogger().isDebugEnabled() )
                          {
                             final String message =
                               "stopping: " + appliance;
                             getLogger().debug( message );
                          }
                          ((Startable)object).stop();
                      }
                  }
                  m_components.remove( appliance );
              }
          }
      }
  
      /**
       * Adds a <code>StateListener</code>.
       * @param listener the state listener to add
       */
      public void addStateListener( StateListener listener )
      {
          synchronized( m_listeners )
          {
              m_listeners.add( listener );
          }
      }
  
      /**
       * Removes a <code>StateListener</code>.
       * @param listener the state listener to remove
       */
      public void removeStateListener( StateListener listener )
      {
          synchronized( m_listeners )
          {
              m_listeners.remove( listener );
          }
      }
  
      /**
       * Notifies all state listeners of a change in the state of the container.
       * @param event the state event.
       */
      protected void fireStateChange( StateEvent event )
      {
          synchronized( m_listeners )
          {
              StateListener[] listeners =
                  (StateListener[])m_listeners.toArray( new StateListener[ 0 ] );
  
              for( int i = 0; i < listeners.length; i++ )
              {
                  StateListener listener = listeners[ i ];
                  try
                  {
                      listener.stateChanged( event );
                  }
                  catch( Exception e )
                  {
                      m_listeners.remove( listener );
                      final String warning =
                          "State listener raised on error on notification - removing listener: "
                          + listener;
                      if( getLogger().isWarnEnabled() )
                      {
                          getLogger().warn( warning );
                      }
                  }
              }
          }
      }
  }
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/impl/DefaultContainer.xinfo
  
  Index: DefaultContainer.xinfo
  ===================================================================
  <?xml version="1.0"?>
  <!DOCTYPE type
        PUBLIC "-//AVALON/Component Type DTD Version 1.1//EN"
               "http://jakarta.apache.org/avalon/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 mailto:avalon-dev@jakarta.apache.org
  @version 1.0 12/03/2001
  -->
  
  <type>
  
    <info>
      <name>container</name>
      <version>1.0</version>
    </info>
  
    <context>
      <entry key="urn:merlin:container.descriptor"
        type="org.apache.avalon.merlin.container.ContainerDescriptor"/>
      <entry key="urn:merlin:container.listener"
        type="org.apache.avalon.merlin.container.StateListener"/>
      <entry key="urn:merlin:container.dependency-graph"
        type="org.apache.avalon.assembly.appliance.DependencyGraph"/>
    </context>
  
  </type>
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/container/impl/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>The container impl package provides the implementation of a heirachical containment runtime environment.</p> 
  </body>
  
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/DefaultKernel.java
  
  Index: DefaultKernel.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.kernel.impl;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.FileInputStream;
  import java.io.InputStream;
  import java.net.URL;
  import java.net.MalformedURLException;
  import java.util.List;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.Enumeration;
  import java.util.jar.JarFile;
  import java.util.jar.Attributes;
  import java.util.jar.Manifest;
  import java.util.zip.ZipEntry;
  import java.net.JarURLConnection;
  
  import org.apache.avalon.assembly.logging.LoggingManager;
  import org.apache.avalon.assembly.logging.LoggingDescriptor;
  import org.apache.avalon.assembly.logging.DefaultLoggingManager;
  import org.apache.avalon.assembly.engine.EngineClassLoader;
  import org.apache.avalon.assembly.engine.Engine;
  import org.apache.avalon.assembly.engine.model.LibraryDescriptor;
  import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
  import org.apache.avalon.assembly.util.ExceptionHelper;
  import org.apache.avalon.assembly.appliance.Appliance;
  import org.apache.avalon.assembly.appliance.ApplianceContext;
  import org.apache.avalon.assembly.appliance.DefaultApplianceContext;
  import org.apache.avalon.assembly.appliance.DependencyGraph;
  import org.apache.avalon.assembly.locator.Contextualizable;
  import org.apache.avalon.assembly.locator.Locator;
  import org.apache.avalon.assembly.locator.DefaultLocator;
  import org.apache.avalon.framework.CascadingException;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.service.DefaultServiceManager;
  import org.apache.avalon.merlin.block.Block;
  import org.apache.avalon.merlin.block.BlockLoader;
  import org.apache.avalon.merlin.block.impl.DefaultBlockLoader;
  import org.apache.avalon.merlin.block.BlockException;
  import org.apache.avalon.merlin.container.builder.XMLContainerCreator;
  import org.apache.avalon.merlin.container.Container;
  import org.apache.avalon.merlin.service.DefaultRegistry;
  import org.apache.avalon.merlin.service.Registry;
  import org.apache.avalon.merlin.kernel.Kernel;
  import org.apache.avalon.merlin.kernel.KernelException;
  import org.apache.avalon.merlin.kernel.KernelRuntimeException;
  import org.apache.avalon.meta.model.LoggingDirective;
  import org.apache.avalon.meta.model.Profile;
  import org.apache.avalon.meta.info.Type;
  import org.apache.excalibur.configuration.ConfigurationUtil;
  
  /**
   * Default kernel implementation.  The implementation provides support for
   * the following sequence of activties:
   *
   * <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>
   *
   * @author <a href="mailto:avalon-dev@jakarta.apache.org">Avalon Development Team</a>
   * @version $Revision: 1.1 $ $Date: 2003/01/19 15:53:56 $
   * @see Block
   */
  
  public class DefaultKernel extends AbstractLogEnabled implements Kernel, Contextualizable, Initializable, Startable, Disposable
  {
      //==============================================================
      // static
      //==============================================================
  
      /**
       * The logging manager that we use to construct logging catagories
       * and logging channels.
       */
      private static LoggingManager LOGGING;
  
      protected static final String BLOCK_XML_ENTRY = "BLOCK-INF/block.xml";
  
      protected static final XMLContainerCreator CREATOR = new XMLContainerCreator();
  
     /**
      * Return a configuration element relative to a target name.  The implementation 
      * will locate a configuration child in the supplied configuration with an element name
      * of "configuration" with a attribute named "target" with a value corresponding to 
      * the supplied name.
      * @param config the configuration holding a set of child "configuration" elements
      * @param name the name to match against child "target" attribute names
      * @return the matching configuration or new empty configuration if no match found
      */
      public static Configuration getNamedConfiguration( Configuration config, String name )
      {
          int i = config.getChildren("configuration").length;
          if( i < 1 )
          {
              return new DefaultConfiguration( "configuration", DefaultKernel.class.getName() );
          }
          return ConfigurationUtil.matchFirstOccurance( config, "configuration", "target", name );
      }
  
      //==============================================================
      // state
      //==============================================================
  
     /**
      * The kernel configuration.
      */
      private Configuration m_kernelConfig;
      
     /**
      * The block configuration.
      */
      private Configuration m_configuration;
      
     /**
      * The application home directory.
      */
      private File m_home;
  
      /**
       * Logging channel for the container.
       */
      private Logger m_logger;
  
      /**
       * Logging channel for the kernel;
       */
      private Logger m_local;
  
      /**
       * The bootstrap classloader.
       */
      private ClassLoader m_bootstrap;
  
      /**
       * The assembly engine.
       */
      private EngineClassLoader m_engine;
  
      /**
       * The system context.
       */
      private DefaultLocator m_system;
  
      /**
       * The list of blocks established by the kernel.
       */
      private List m_blocks = new ArrayList();   
  
      /**
       * A map of root containers keyed by the block it is contained by.
       */
      private Map m_containers = new Hashtable();
  
      private DefaultRegistry m_registry;
  
      private final DependencyGraph m_graph = new DependencyGraph();
  
      //==============================================================
      // Contextualizable
      //==============================================================
  
     /**
      * <p>Application of a runtime context to the kernel.
      * Context entries that may be supplied to an appliance manager are 
      * detailed in the following table.</p>
      * <table BORDER="1" CELLSPACING="0" CELLPADDING="3" WIDTH="90%" >
      *   <tr BGCOLOR="#EEEEFF">
      *     <td><b>key</b></td><td><b>type</b></td><td><b>description</b></td>
      *   </tr>
      *   <tr>
      *     <td><code>urn:assembly:home</code></td>
      *     <td>{@link java.io.File}</td>
      *     <td>The kernel home directory.</td> 
      *   </tr>
      * </table>
      * @param context the runtime context
      * @exception ContextException if an error occurs during the contextualization phase
      */
      public void contextualize( Locator context ) throws ContextException
      {
          m_home = (File) context.get( "urn:assembly:home" );
          m_bootstrap = (ClassLoader) context.get( "urn:avalon:classloader" );
      }
  
      //==============================================================
      // Initializable
      //==============================================================
  
     /**
      * Initialization of the kernel.  The implementation hanldes the
      * establishment of the logging system, bootstraps the assembly
      * engine, loads all blocks declared in the kernel configuration,
      * initiates block assembly and list available services.
      *
      * @exception Exception if an initialization error occurs.
      */
      public void initialize() throws Exception
      {
          if( m_home == null )
          {
               throw new IllegalStateException("context");
          }
  
          //
          // load the kernel configuration
          //
  
          File kernelFile = new File( m_home, "kernel.xml" );
          try
          {
              m_kernelConfig = getConfiguration( kernelFile );
          }
          catch( Throwable e )
          {
              final String error =
                "Unable to load kernel configuration from file: "
                + kernelFile;
              throw new CascadingException( error, e );
          }
  
          //
          // load the blocks configuration
          //
  
          File blocksFile = new File( m_home, "blocks.xml" );
          try
          {
              m_configuration = getConfiguration( blocksFile );
          }
          catch( Throwable e )
          {
              final String error =
                "Unable to load blocks configuration from file: "
                + kernelFile;
              throw new CascadingException( error, e );
          }
  
          //
          // Setup the logging system
          //
  
          try
          {
              if( LOGGING == null )
              {
                  LOGGING = bootstrapLoggingManager( Container.PATH_SEPERATOR );
                  Configuration categoriesConfig = m_kernelConfig.getChild( "categories" );
                  LoggingDirective categories =
                    CREATOR.createLoggingDirective( Container.PATH_SEPERATOR, categoriesConfig );
                  LOGGING.addCategories( Container.PATH_SEPERATOR, categories );
              }
              final String sys = "/sys";
              m_local = LOGGING.getLoggerForCategory( sys );
              enableLogging( m_local );
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while establishing the logging subsystem.";
              throw new CascadingException( error, e );
          }
  
          String domain = m_kernelConfig.getChild( "system" ).getAttribute( "host", "localhost" );
          m_registry = new DefaultRegistry( domain );
          
          //
          // announce initialization
          //
  
          if( getLogger().isInfoEnabled() )
          {
              getLogger().info( "initialization from: " + m_home + " on " + domain );
          }
  
          //
          // setup the bootstrap assembly engine
          //
  
          try
          {
              m_engine = bootstrapEngine( LOGGING, m_kernelConfig.getChild( "engine" ) );
          }
          catch( Throwable e )
          {
              final String error = 
                "Bootstrap engine establishment error.  Extension path: " 
                + System.getProperty("java.ext.dirs");
              String log = ExceptionHelper.packException( error, e );
              if( getLogger().isErrorEnabled() )
              {
                  getLogger().error( log );
              }
              throw new KernelException( error, e );
          }
  
          //
          // we are now ready to assemble the blocks declared under the 
          // kernel configuration
          //
  
          if( getLogger().isInfoEnabled() )
          {
              getLogger().info( "\n\ncommencing block construction phase\n" );
          }
  
          Block[] blocks;
  
          try
          {
              DefaultBlockLoader loader = new DefaultBlockLoader();
              loader.enableLogging( getLogger() );
              DefaultLocator context = new DefaultLocator();
              context.put( "urn:assembly:engine", m_engine );
              context.put( "urn:assembly:registry", m_registry );
              context.put( "urn:assembly:system-context", getSystemContext() );
              context.makeReadOnly();
              loader.contextualize( context );
              loader.initialize();
  
              blocks = loader.createBlocks( m_configuration );
  
              for( int i=0; i<blocks.length; i++ )
              {
                  Block block = blocks[i];
                  m_blocks.add( block );
                  if( getLogger().isInfoEnabled() )
                  {
                      getLogger().info( block.toString() );
                  }
              }
  
              loader.dispose();
          }
          catch( Throwable e )
          {
              final String error = "Block installation phase failure.";
              String log = ExceptionHelper.packException( error, e );
              if( getLogger().isErrorEnabled() )
              {
                  getLogger().error( log );
              }
              throw new KernelException( error, e );
          }
  
          //
          // Instantiate the root container in each block.
          //
  
          if( getLogger().isInfoEnabled() )
          {
              getLogger().info( "\n\ncommencing structural assembly phase\n" );
          }
  
          for( int i=0; i<blocks.length; i++ )
          {
              Block block = blocks[i];
              try
              {
                  block.assemble( new DependencyGraph( m_graph ) );
              }
              catch( Throwable e )
              {
                  final String error = 
                    "Unable to deploy block: " + block + " due to a structural assembly failure.";
                  String log = ExceptionHelper.packException( error, e );
                  if( getLogger().isErrorEnabled() )
                  {
                      getLogger().error( log );
                  }
                  throw new KernelException( error, e );
              }
          }
          
          //
          // list the registered services
          //
  
          URL[] appliances = m_registry.list();
          if( appliances.length == 0 )
          {
              getLogger().info( "empty registry" ); 
          }
          else
          {
              for( int i=0; i<appliances.length; i++ )
              {
                 getLogger().info("registry: " + appliances[i] ); 
              }
          }
      }
  
      //==============================================================
      // Startable
      //==============================================================
  
     /**
      * Start the kernel.
      *
      * @exception Exception if an startup error occurs.
      */
      public void start() throws Exception 
      {
          if( getLogger().isInfoEnabled() )
          {
              getLogger().info( "\n\ncommencing deployment phase\n" );
          }
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
              block.deploy();
          }
  
          if( getLogger().isInfoEnabled() )
          {
              getLogger().info( "\n\ndeployment complete\n" );
          }
      }
  
     /**
      * Stop the kernel.
      *
      * @exception Exception if an shutdown error occurs.
      */
      public void stop() throws Exception 
      {
          if( getLogger() != null ) 
          {
              if( getLogger().isInfoEnabled() )
              {
                  getLogger().info( "\n\ncommencing decommissioning phase\n" );
              }
          }
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
              block.decommission();
          }
      }
  
      //==============================================================
      // Disposable
      //==============================================================
  
     /**
      * Disposal of the kernel.  
      */
      public void dispose()
      {
          if( getLogger() != null ) 
          {
              if( getLogger().isInfoEnabled() )
              {
                  getLogger().info( "\n\ncommencing termination phase\n" );
              }
          }
  
          Iterator iterator = m_blocks.iterator();
          while( iterator.hasNext() )
          {
              Block block = (Block) iterator.next();
              block.terminate();
          }
  
          if( getLogger() != null )
          {
              if( getLogger().isInfoEnabled() )
              {
                  getLogger().info( "bye" );
              }
          }
      }
  
      //==============================================================
      // internals
      //==============================================================
  
      private LoggingManager bootstrapLoggingManager( String root ) throws Exception
      {
          if( m_kernelConfig == null )
          {
              throw new IllegalStateException( "configuration" );
          }
          if( m_home == null )
          {
              throw new IllegalStateException( "context" );
          }
          if( CREATOR == null )
          {
              throw new NullPointerException( "creator" );
          }
  
          try
          {
              DefaultLoggingManager logging = new DefaultLoggingManager();
  
              LoggingDescriptor descriptor =
                CREATOR.createLoggingDescriptor( 
                  m_kernelConfig.getChild( "logging" ), root );
  
              DefaultLocator context = new DefaultLocator();
              context.put( "urn:assembly:home", m_home );
              context.put( "urn:assembly:logging.descriptor", descriptor );
              context.makeReadOnly();
  
              logging.contextualize( context );
              logging.initialize();
              return logging;
          }
          catch( Throwable e )
          {
              final String error = 
                "Internal error while bootstrapping the logging subsystem.";
              throw new CascadingException( error, e );
          }
      }
  
      private EngineClassLoader bootstrapEngine( 
        LoggingManager logging, Configuration config ) 
        throws Exception
      {
          if( m_home == null )
          {
              throw new IllegalStateException( "context" );
          }
          if( getLogger() == null )
          {
              throw new IllegalStateException( "logging" );
          }
          if( CREATOR == null )
          {
              throw new NullPointerException( "creator" );
          }
  
          if( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "bootstrap engine" );
          }
  
          LibraryDescriptor extensions =
            CREATOR.createLibraryDescriptor( config.getChild( "library" ) );
  
          ClasspathDescriptor classpath = 
            CREATOR.createClasspathDescriptor( config.getChild( "classpath" ) );
  
          try
          {
              EngineClassLoader engine = new EngineClassLoader( m_bootstrap );
              engine.enableLogging( getLogger() );
              Locator system = getSystemContext();
              DefaultLocator context = new DefaultLocator( system );
              context.put( "urn:assembly:engine.bootstrap", "true" );
              context.put( "urn:assembly:engine.extensions", extensions );
              context.put( "urn:assembly:engine.classpath", classpath );
              context.put( "urn:assembly:logging.manager", logging );
              context.makeReadOnly();
              engine.contextualize( context );
              engine.initialize();
              return engine;
          }
          catch( Throwable e )
          {
              final String error = "Engine bootstrap failure.";
               throw new CascadingException( error, e );
          }
      }
  
     /**
      * Return a string representation of the kernel.
      * @return the string representation
      */
      public String toString()
      {
          return "DefaultKernel"
            + ":" + System.identityHashCode( this );
      }
  
     /**
      * Create the system context.
      * @return the system context
      */
      private Locator getSystemContext()
      {
          if( m_system == null )
          {
              DefaultLocator context = new DefaultLocator();
              context.put( "urn:assembly:home", m_home );
              context.put( "urn:merlin:domain", m_registry.getBase().getHost() );
              context.makeReadOnly();
              m_system = context;
          }
          return m_system;
      }
  
      private Configuration getConfiguration( final File file ) throws ConfigurationException
      {
          try
          {
              DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
              InputStream is = new FileInputStream( file );
              if( is == null )
              {
                  throw new ConfigurationException(
                      "Could not load the configuration resource \"" + file + "\"" );
              }
              return builder.build( is );
          }
          catch( Throwable e )
          {
              final String error = "Unable to create configuration from file: " + file;
              throw new ConfigurationException( error, e );
          }
      }
  }
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/DefaultKernel.xinfo
  
  Index: DefaultKernel.xinfo
  ===================================================================
  <?xml version="1.0"?>
  <!DOCTYPE type
        PUBLIC "-//AVALON/Component Type DTD Version 1.0//EN"
               "http://jakarta.apache.org/avalon/dtds/meta/type_1_0.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  Stephen McConnell
  @version 1.0 12/03/2001
  -->
  
  <type>
  
    <info>
      <name>kernel</name>
      <version>1.0</version>
    </info>
  
    <context>
      <entry key="urn:assembly:home" type="java.io.File" />
      <entry key="urn:avalon:classloader" type="java.lang.ClassLoader" />
    </context>
  
    <services>
      <service>
        <reference type="org.apache.avalon.merlin.kernel.Kernel" version="1.0"/>
      </service>
    </services>
  
  </type>
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/KernelLoader.java
  
  Index: KernelLoader.java
  ===================================================================
  
  
  package org.apache.avalon.merlin.kernel.impl;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.FileInputStream;
  import java.io.InputStream;
  import java.io.IOException;
  import java.io.FileNotFoundException;
  import java.util.StringTokenizer;
  import java.util.Enumeration;
  import java.util.List;
  import java.util.Iterator;
  import java.util.jar.JarFile;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.jar.Attributes;
  import java.util.jar.Manifest;
  import java.net.URLClassLoader;
  import java.net.URL;
  import java.util.zip.ZipEntry;
  import java.net.MalformedURLException;
  import java.net.JarURLConnection;
  
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.DefaultContext;
  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.assembly.util.ExceptionHelper;
  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.merlin.kernel.Kernel;
  import org.apache.avalon.merlin.kernel.KernelException;
  import org.apache.avalon.merlin.kernel.KernelRuntimeException;
  
  /**
   * Merlin commandline bootstrap handler.
   * @see DefaultKernel
   */
  public class KernelLoader
  {
  
      private DefaultKernel m_kernel;
  
      public KernelLoader( ClassLoader loader, File base )
      {
          try
          {
              m_kernel = new DefaultKernel();
          }
          catch( Throwable e )
          {
              final String error =
                "\nUnexpected exception while attempting to load kernel loader from classloader: " 
                + loader + " with parent: " + loader.getParent();
              e.printStackTrace();
              throw new KernelRuntimeException( error, e );
          }
  
          try
          {
              Runtime.getRuntime().addShutdownHook(
                new Thread()
                {
                  public void run()
                  {
                      try
                      {
                          m_kernel.stop();
                      }
                      catch( Throwable e )
                      {
                          // ignore it
                      }
                      finally
                      {
                          m_kernel.dispose();
                      }
                  }
                }
              );
          }
          catch( IllegalStateException ise )
          {
               if( m_kernel != null )
               {
                   try
                   {
                       m_kernel.stop();
                   }
                   catch( Throwable e )
                   {
                       // ignore it
                   }
                   finally
                   {
                       m_kernel.dispose();
                   }
               }
               return;
          }
  
          DefaultLocator context = new DefaultLocator();
          context.put( "urn:assembly:home", base );
          context.put( "urn:avalon:classloader", loader );
          context.makeReadOnly();
  
          try
          {
              m_kernel.contextualize( context );
              m_kernel.initialize();
              m_kernel.start();
          }
          catch( KernelException e )
          {
              // its already been logged
          }
          catch( BlockException e )
          {
              // its already been logged
          }
          catch( Throwable e )
          {
              final String error = "Controller deployment failure.";
              String message = ExceptionHelper.packException( error, e );
              System.err.println( message );
              m_kernel.dispose();
          }
      }
  }
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/Resources.properties
  
  Index: Resources.properties
  ===================================================================
  xinfo-load=Creating Type from {0}.
  xinfo-missing=XINFO resource unavailable for class "{0}".
  xinfo-parse-error=Error occured while parsing xinfo resource "{0}".
  xinfo-nocreate=Failed to create Type from resource "{0}" (Reason: {1}).
  xinfo-props-error=Unable to construct attributes using key "{0}" (Reason: {1}).
  cinfo-nocreate=Failed to create Type from resource "{0}" (Reason: {1}).
  cinfo-properties-error=Failed to create Type attributes from resource "{0}" (Reason: {1}).
  sinfo-noname=Missing name attribute in service declaration from resource "{0}".
  sinfo-version=Bad service version in resource "(Reason: {0})".
  sinfo-nocreate=Failed to create ServiceInfo from resource "{0}" (Reason: {1}).
  dinfo-service-error="Could not create dependecy service delcaration (Reason: {0}).
  dinfo-nocreate="Could not create dependecy delcaration from resource "{0}" (Reason: {1}).
  
  resource.missing-context-value.error=Missing {0,choice,1#Optional|2#Required} Context Entry with key "{1}" for component named "{2}".
  resource.bad-value-type.error=Bad value retrieved for {0,choice,1#Optional|2#Required} Context Entry with key "{1}" for component named "{2}". Expected to be of type "{3}" but was of type "{4}".
  resource.bad-context-type.error=The class of Contex object for component named "{2}" was expected to be of type {0} but was of tpye {1}.
  resource.service-not-a-component.error=The service with role "0" and implemenation class "{1}" does not implement the Component interface but is being exposed via ComponentManager.
  resource.missing-dependency.error=Missing {0,choice,1#Optional|2#Required} dependency with role "{1}" for component named {2}.
  resource.missing-parameters.error=Missing Parameters object for component named "{0}".
  resource.missing-parameters.error=Missing Configuration for component named "{0}".
  
  
  
  
  1.1                  avalon-sandbox/merlin/src/java/org/apache/avalon/merlin/kernel/impl/package.html
  
  Index: package.html
  ===================================================================
  
  <body>
  <p>
  The kernel package defines a top level Kernel that serves as a host to a set of Blocks. The default kernel implementation handles the setup of supporting infrastructure and deployment of declared blocks.
  </p>
  <p>
    <table border="1" cellpadding="3" cellspacing="0" width="100%">
      <tr bgcolor="#ccccff">
        <td colspan="2"><font size="+2"><b>Component Summary</b></font></td>
      <tr>
        <td width="20%" valign="top"><strong>{@link org.apache.avalon.merlin.kernel.DefaultKernel}</strong></td>
        <td>A <code>{@link org.apache.avalon.merlin.kernel.Kernel}</code> implementation that provides support the establishment, deployment and decommissioning of a set of {@link org.apache.avalon.merlin.block.Block } instances.</td></tr>
      </tr>
    </table>
  </p>
  </body>
  
  
  
  

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