Return-Path: Delivered-To: apmail-avalon-cvs-archive@avalon.apache.org Received: (qmail 87640 invoked by uid 500); 20 Apr 2003 12:18:06 -0000 Mailing-List: contact cvs-help@avalon.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Avalon CVS List" Reply-To: "Avalon Developers List" Delivered-To: mailing list cvs@avalon.apache.org Received: (qmail 87629 invoked by uid 500); 20 Apr 2003 12:18:06 -0000 Received: (qmail 87626 invoked from network); 20 Apr 2003 12:18:06 -0000 Received: from icarus.apache.org (208.185.179.13) by daedalus.apache.org with SMTP; 20 Apr 2003 12:18:06 -0000 Received: (qmail 2313 invoked by uid 1438); 20 Apr 2003 12:18:06 -0000 Date: 20 Apr 2003 12:18:06 -0000 Message-ID: <20030420121806.2312.qmail@icarus.apache.org> From: mcconnell@apache.org To: avalon-sandbox-cvs@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 X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N 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 . */ 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 block 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 . */ 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. * *
    *
  • loading kernel.xml configuration *
  • loading blocks.xml configuration *
  • establishment of the logging system *
  • loading internal jar-file dependencies *
  • establishment of a root component management engine *
  • block abstraction that encapsulates a heirachical container model *
  • block configuration repository *
  • block assembly, deployment and decommissioning *
  • management of interupt conditions and kernel disposal *
  • error management *
* * WARNING: This class is in the process of refactoring. * * @author Stephen McConnell * @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 <info> 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 <info> 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