mcconnell 02/03/03 07:45:59
Modified: enterprise/tools/lib avalon-framework.jar
Added: enterprise/tools/etc overview.html
enterprise/tools/lib .cvsignore merlin.jar
enterprise/tools/src/etc LICENSE.HTML LICENSE.TXT README.TXT
demo.mf license.css loader.mf
enterprise/tools/src/java/org/apache/avalon/excalibur/configuration
CascadingConfiguration.java package.html
enterprise/tools/src/java/org/apache/avalon/excalibur/service
DefaultServiceManager.java DependencyInfo.java
PipelineException.java
PipelineRuntimeException.java ServiceContext.java
ServiceFactory.java ServiceInfo.java
ServiceLoader.java ServiceLoaderContext.java
ServiceProvider.java ServiceRegistry.java
SingletonProvider.java TransientProvider.java
UnitInfo.java package.html
enterprise/tools/src/java/org/apache/avalon/excalibur/service/ant
Load.java
enterprise/tools/src/java/org/apache/avalon/phoenix
Block.java BlockContext.java
enterprise/tools/src/java/org/apache/demo
DirectoryBlock.java DirectoryBlock.xinfo
DirectoryService.java ReferralBlock.java
ReferralBlock.xinfo ReferralService.java
Log:
addition of service management and service loading framework
Revision Changes Path
1.1 jakarta-avalon-apps/enterprise/tools/etc/overview.html
Index: overview.html
===================================================================
<body>
</body>
1.2 +33 -28
jakarta-avalon-apps/enterprise/tools/lib/avalon-framework.jar
<<Binary file>>
1.1 jakarta-avalon-apps/enterprise/tools/lib/.cvsignore
Index: .cvsignore
===================================================================
merlin.jar
1.1 jakarta-avalon-apps/enterprise/tools/lib/merlin.jar
<<Binary file>>
1.1 jakarta-avalon-apps/enterprise/tools/src/etc/LICENSE.HTML
Index: LICENSE.HTML
===================================================================
<HTML>
<HEAD>
<LINK rel="stylesheet" type="text/css" href="license.css" title="index">
<TITLE>Persistent State Service (PSS) License and Due Credits</TITLE>
<META name="description"
content="Persistent State Service (PSS) Open Source License">
<META name="keywords" content="pss, omg, apache, osm">
</HEAD>
<BODY BGCOLOR="#ffffff">
<p class="title">Persistent State Service (PSS) <br>Disclaimers,
Licenses and Due Credits</p>
<hr>
<p class="sub-title">The Apache Software License, Version 1.1</p>
<pre class="pre">
Copyright (C) 1997-2001 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Jakarta", "Avalon", "Excalibur", "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 [EMAIL PROTECTED]
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/>.
</pre>
<hr>
Initial submissions of the service management utilities provided under the
Excalibur Service package together with cascading configuration utilities
have been provided by OSM <a href="http://www.osm.net">http://www.osm.net</a>.
</body>
</html>
1.1 jakarta-avalon-apps/enterprise/tools/src/etc/LICENSE.TXT
Index: LICENSE.TXT
===================================================================
Disclaimers, Licenses and Due Credits
================================================================================
The Apache Software License, Version 1.1
================================================================================
Copyright (C) 1997-2001 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Jakarta", "Avalon", "Excalibur", "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 [EMAIL PROTECTED]
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/>.
================================================================================
Due Credits
================================================================================
Initial submissions of the service management utilities provided under the
Excalibur Service package together with cascading configuration utilities
have been provided by OSM http://www.osm.net.
1.1 jakarta-avalon-apps/enterprise/tools/src/etc/README.TXT
<<Binary file>>
1.1 jakarta-avalon-apps/enterprise/tools/src/etc/demo.mf
Index: demo.mf
===================================================================
Manifest-Version: 1.0
Name: org/apache/demo/DirectoryBlock.class
Avalon-Block: true
Name: org/apache/demo/ReferralBlock.class
Avalon-Block: true
1.1 jakarta-avalon-apps/enterprise/tools/src/etc/license.css
Index: license.css
===================================================================
A:link {color: blue}
A:visited {color: lightslategray}
A:active {color: blue}
H1 {
font-size: 12pt; color: black; font-style: normal; font-weight:
normal;
margin-left: 9px; margin-top: 20px; margin-bottom: 12px; font-family:
serif;
}
.logo {
position:absolute;
top:35px; left:0px;
}
.title {
font-size: 12pt; color: black;
margin-left: 9px; margin-top: 120px; margin-bottom: 12px;
}
.title2 {
font-size: 12pt; color: black;
margin-left: 9px; margin-top: 20px; margin-bottom: 12px;
}
.cover {
horizontal-align: center; text-align: center;
margin-left: 9px; margin-top: 3px; margin-bottom: 3px;
}
.sub-title {
font-size: 12pt; color: black;
margin-left: 9px; margin-top: 6px; margin-bottom: 12px;
}
.pre {
margin-left: 37px;
}
.map {
horizontal-align: center; text-align: center;
margin: 3px; margin-top: 48px;
}
.picture {
horizontal-align: center; text-align: center;
margin: 9px;
}
.figure {
horizontal-align: center; text-align: center; font-style: italic;
margin: 36px;
}
.icon {
vertical-align: bottom;
margin-left: 3px; margin-top: 24px; margin-right 24px;
}
.note {
vertical-align: bottom;
margin-left: 24px; margin-top: 3px; margin-right: 60px;
font-style: italic;
}
.menu {
vertical-align: bottom; font-size: 10pt; font-style: italic; color:
black;
margin-left: 9px; margin-top: 9px; margin-bottom: 6px;
}
.menu2 {
vertical-align: bottom; font-size: 10pt; font-style: italic; color:
black;
margin-left: 37px; margin-top: 3px; margin-bottom: 3px;
}
.item {
vertical-align: bottom; font-size: 10pt; font-style: italic; color:
black;
margin-left: 9px; margin-top: 9px; margin-bottom: 6px;
}
.body {
margin-left: 9px; font-size: 12pt;
}
.legal {
vertical-align: bottom; font-size: 10pt; color: black;
margin-left: 9px;
}
1.1 jakarta-avalon-apps/enterprise/tools/src/etc/loader.mf
Index: loader.mf
===================================================================
Manifest-Version: 1.0
Main-Class: org.apache.avalon.excalibur.service.ServiceLoader
Class-Path: avalon-framework.jar logkit-1.0.jar
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/configuration/CascadingConfiguration.java
Index: CascadingConfiguration.java
===================================================================
/**
* File: CascadingConfiguration.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2001-2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.configuration;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
/**
* The CascadingConfiguration is a classic Configuration backed by parent
* Configuration. Operations such as getChild return a CascadingConfiguration
* encapsulating both a primary and parent configuration. Requests for
attribute
* values are resolved against the base configuration initially. If the
result
* of the resolution is unsucessful, the request is applied against the parent
* configuration. As a parent may also be a CascadingConfiguration, the
evaluation
* will be applied until a value is resolved against a class parent
Configuration.
* @author Stephen McConnell <[EMAIL PROTECTED]>
*/
public class CascadingConfiguration implements Configuration
{
//=============================================================================
// state
//=============================================================================
private final Configuration m_base;
private final Configuration m_parent;
//=============================================================================
// constructors
//=============================================================================
/**
* Create a CascadingConfiguration with specified parent. The base
* configuration shall override a parent configuration on request for
* attribute values and configuration body values. Unresolved request
* are redirected up the parent chain until a classic configuration is
* reached. Request for child configurations will return a
* new CascadingConfiguration referencing the child of the base and
* the child of the primary (i.e. a child configuration chain).
*
* @param base the base Configuration
* @param parent the parent Configuration
*/
public CascadingConfiguration( final Configuration base , final
Configuration parent )
{
if( base == null )
{
m_base = new DefaultConfiguration( "-", null );
}
else
{
m_base = base;
}
if( parent == null )
{
m_parent = new DefaultConfiguration( "-", null );
}
else
{
m_parent = parent;
}
}
//=============================================================================
// Configuration
//=============================================================================
/**
* Return the name of the base node.
* @return name of the <code>Configuration</code> node.
*/
public String getName()
{
return m_base.getName();
}
/**
* Return a string describing location of the base Configuration.
* Location can be different for different mediums (ie "file:line" for
normal XML files or
* "table:primary-key" for DB based configurations);
*
* @return a string describing location of Configuration
*/
public String getLocation()
{
return m_base.getLocation();
}
/**
* Returns the namespace the main Configuration node
* belongs to.
* @since 4.1
* @return a Namespace identifying the namespace of this Configuration.
*/
public String getNamespace() throws ConfigurationException
{
return m_base.getNamespace();
}
/**
* Return a new <code>CascadingConfiguration</code> instance
encapsulating the
* specified child node of the base and parent node.
*
* @param child The name of the child node.
* @return Configuration
*/
public Configuration getChild( String child )
{
return new CascadingConfiguration( m_base.getChild( child ),
m_parent.getChild( child ) );
}
/**
* Return a <code>Configuration</code> instance encapsulating the
specified
* child node.
*
* @param child The name of the child node.
* @param createNew If <code>true</code>, a new <code>Configuration</code>
* will be created and returned if the specified child does not exist in
either
* the base or parent configuratioin. If <code>false</code>,
<code>null</code>
* will be returned when the specified child doesn't exist in either the
base or
* the parent.
* @return Configuration
*/
public Configuration getChild( String child, boolean createNew )
{
if( createNew ) return getChild( child );
Configuration c = m_base.getChild( child, false );
if( child != null ) return c;
return m_parent.getChild( child, false );
}
/**
* Return an <code>Array</code> of <code>Configuration</code>
* elements containing all node children of both base and parent
configurations.
* The array order will reflect the order in the source config file,
commencing
* with the base configuration.
*
* @return All child nodes
*/
public Configuration[] getChildren()
{
Configuration[] b = m_base.getChildren( );
Configuration[] p = m_parent.getChildren( );
Configuration[] result = new Configuration[ b.length + p.length ];
System.arraycopy(b, 0, result, 0, b.length );
System.arraycopy(p, 0, result, b.length, p.length );
return result;
}
/**
* Return an <code>Array</code> of <code>Configuration</code>
* elements containing all node children with the specified name from
* both base and parent configurations. The array
* order will reflect the order in the source config file commencing
* with the base configuration.
*
* @param name The name of the children to get.
* @return The child nodes with name <code>name</code>
*/
public Configuration[] getChildren( String name )
{
Configuration[] b = m_base.getChildren( name );
Configuration[] p = m_parent.getChildren( name );
Configuration[] result = new Configuration[ b.length + p.length ];
System.arraycopy(b, 0, result, 0, b.length );
System.arraycopy(p, 0, result, b.length, p.length );
return result;
}
/**
* Return an array of all attribute names in both base and parent.
* <p>
* <em>The order of attributes in this array can not be relied on.</em> As
* with XML, a <code>Configuration</code>'s attributes are an
* <em>unordered</em> set. If your code relies on order, eg
* <tt>conf.getAttributeNames()[0]</tt>, then it is liable to break if a
* different XML parser is used.
* </p>
*/
public String[] getAttributeNames()
{
java.util.Vector vector = new java.util.Vector();
String[] names = m_base.getAttributeNames();
String[] names2 = m_parent.getAttributeNames();
for( int i=0; i<names.length; i++ )
{
vector.add( names[i] );
}
for( int i=0; i<names2.length; i++ )
{
if( vector.indexOf( names2[i] ) < 0 ) vector.add( names2[i] );
}
return (String[]) vector.toArray( new String[0] );
}
/**
* Return the value of specified attribute. If the base configuration
* does not contain the attribute, the equivialent operation is applied
to
* the parent configuration.
*
* @param paramName The name of the parameter you ask the value of.
* @return String value of attribute.
* @exception ConfigurationException If no attribute with that name
exists.
*/
public String getAttribute( String paramName ) throws
ConfigurationException
{
try
{
return m_base.getAttribute( paramName );
}
catch( ConfigurationException e )
{
return m_parent.getAttribute( paramName );
}
}
/**
* Return the <code>int</code> value of the specified attribute contained
* in this node or the parent.
* @param paramName The name of the parameter you ask the value of.
* @return int value of attribute
* @exception ConfigurationException If no parameter with that name
exists.
* or if conversion to <code>int</code>
fails.
*/
public int getAttributeAsInteger( String paramName ) throws
ConfigurationException
{
try
{
return m_base.getAttributeAsInteger( paramName );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsInteger( paramName );
}
}
/**
* Returns the value of the attribute specified by its name as a
* <code>long</code>.
*
* @param paramName The name of the parameter you ask the value of.
* @return long value of attribute
* @exception ConfigurationException If no parameter with that name
exists.
* or if conversion to
<code>long</code> fails.
*/
public long getAttributeAsLong( String name ) throws
ConfigurationException
{
try
{
return m_base.getAttributeAsLong( name );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsLong( name );
}
}
/**
* Return the <code>float</code> value of the specified parameter
contained
* in this node.
* @param paramName The name of the parameter you ask the value of.
* @return float value of attribute
* @exception ConfigurationException If no parameter with that name
exists.
* or if conversion to
<code>float</code> fails.
*/
public float getAttributeAsFloat( String paramName ) throws
ConfigurationException
{
try
{
return m_base.getAttributeAsFloat( paramName );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsFloat( paramName );
}
}
/**
* Return the <code>boolean</code> value of the specified parameter
contained
* in this node.<br>
*
* @param paramName The name of the parameter you ask the value of.
* @return boolean value of attribute
* @exception ConfigurationException If no parameter with that name
exists.
* or if conversion to
<code>boolean</code> fails.
*/
public boolean getAttributeAsBoolean( String paramName ) throws
ConfigurationException
{
try
{
return m_base.getAttributeAsBoolean( paramName );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsBoolean( paramName );
}
}
/**
* Return the <code>String</code> value of the node.
*
* @return the value of the node.
*/
public String getValue() throws ConfigurationException
{
try
{
return m_base.getValue();
}
catch( ConfigurationException e )
{
return m_parent.getValue();
}
}
/**
* Return the <code>int</code> value of the node.
*
* @exception ConfigurationException If conversion to <code>int</code>
fails.
*/
public int getValueAsInteger() throws ConfigurationException
{
try
{
return m_base.getValueAsInteger();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsInteger();
}
}
/**
* Return the <code>float</code> value of the node.
*
* @return the value of the node.
* @exception ConfigurationException If conversion to <code>float</code>
fails.
*/
public float getValueAsFloat() throws ConfigurationException
{
try
{
return m_base.getValueAsFloat();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsFloat();
}
}
/**
* Return the <code>boolean</code> value of the node.
*
* @return the value of the node.
* @exception ConfigurationException If conversion to
<code>boolean</code> fails.
*/
public boolean getValueAsBoolean() throws ConfigurationException
{
try
{
return m_base.getValueAsBoolean();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsBoolean();
}
}
/**
* Return the <code>long</code> value of the node.<br>
*
* @return the value of the node.
* @exception ConfigurationException If conversion to <code>long</code>
fails.
*/
public long getValueAsLong() throws ConfigurationException
{
try
{
return m_base.getValueAsLong();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsLong();
}
}
/**
* Returns the value of the configuration element as a
<code>String</code>.
* If the configuration value is not set, the default value will be
* used.
*
* @param defaultValue The default value desired.
* @return String value of the <code>Configuration</code>, or default
* if none specified.
*/
public String getValue( String defaultValue )
{
try
{
return m_base.getValue();
}
catch( ConfigurationException e )
{
return m_parent.getValue( defaultValue );
}
}
/**
* Returns the value of the configuration element as an <code>int</code>.
* If the configuration value is not set, the default value will be
* used.
*
* @param defaultValue The default value desired.
* @return int value of the <code>Configuration</code>, or default
* if none specified.
*/
public int getValueAsInteger( int defaultValue )
{
try
{
return m_base.getValueAsInteger();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsInteger( defaultValue );
}
}
/**
* Returns the value of the configuration element as a <code>long</code>.
* If the configuration value is not set, the default value will be
* used.
*
* @param defaultValue The default value desired.
* @return long value of the <code>Configuration</code>, or default
* if none specified.
*/
public long getValueAsLong( long defaultValue )
{
try
{
return m_base.getValueAsLong();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsLong( defaultValue );
}
}
/**
* Returns the value of the configuration element as a <code>float</code>.
* If the configuration value is not set, the default value will be
* used.
*
* @param defaultValue The default value desired.
* @return float value of the <code>Configuration</code>, or default
* if none specified.
*/
public float getValueAsFloat( float defaultValue )
{
try
{
return m_base.getValueAsFloat();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsFloat( defaultValue );
}
}
/**
* Returns the value of the configuration element as a
<code>boolean</code>.
* If the configuration value is not set, the default value will be
* used.
*
* @param defaultValue The default value desired.
* @return boolean value of the <code>Configuration</code>, or default
* if none specified.
*/
public boolean getValueAsBoolean( boolean defaultValue )
{
try
{
return m_base.getValueAsBoolean();
}
catch( ConfigurationException e )
{
return m_parent.getValueAsBoolean( defaultValue );
}
}
/**
* Returns the value of the attribute specified by its name as a
* <code>String</code>, or the default value if no attribute by
* that name exists or is empty.
*
* @param name The name of the attribute you ask the value of.
* @param defaultValue The default value desired.
* @return String value of attribute. It will return the default
* value if the named attribute does not exist, or if
* the value is not set.
*/
public String getAttribute( String name, String defaultValue )
{
try
{
return m_base.getAttribute( name );
}
catch( ConfigurationException e )
{
return m_parent.getAttribute( name, defaultValue );
}
}
/**
* Returns the value of the attribute specified by its name as a
* <code>int</code>, or the default value if no attribute by
* that name exists or is empty.
*
* @param name The name of the attribute you ask the value of.
* @param defaultValue The default value desired.
* @return int value of attribute. It will return the default
* value if the named attribute does not exist, or if
* the value is not set.
*/
public int getAttributeAsInteger( String name, int defaultValue )
{
try
{
return m_base.getAttributeAsInteger( name );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsInteger( name, defaultValue );
}
}
/**
* Returns the value of the attribute specified by its name as a
* <code>long</code>, or the default value if no attribute by
* that name exists or is empty.
*
* @param name The name of the attribute you ask the value of.
* @param defaultValue The default value desired.
* @return long value of attribute. It will return the default
* value if the named attribute does not exist, or if
* the value is not set.
*/
public long getAttributeAsLong( String name, long defaultValue )
{
try
{
return m_base.getAttributeAsLong( name );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsLong( name, defaultValue );
}
}
/**
* Returns the value of the attribute specified by its name as a
* <code>float</code>, or the default value if no attribute by
* that name exists or is empty.
*
* @param name The name of the attribute you ask the value of.
* @param defaultValue The default value desired.
* @return float value of attribute. It will return the default
* value if the named attribute does not exist, or if
* the value is not set.
*/
public float getAttributeAsFloat( String name, float defaultValue )
{
try
{
return m_base.getAttributeAsFloat( name );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsFloat( name, defaultValue );
}
}
/**
* Returns the value of the attribute specified by its name as a
* <code>boolean</code>, or the default value if no attribute by
* that name exists or is empty.
*
* @param name The name of the attribute you ask the value of.
* @param defaultValue The default value desired.
* @return boolean value of attribute. It will return the default
* value if the named attribute does not exist, or if
* the value is not set.
*/
public boolean getAttributeAsBoolean( String name, boolean defaultValue )
{
try
{
return m_base.getAttributeAsBoolean( name );
}
catch( ConfigurationException e )
{
return m_parent.getAttributeAsBoolean( name, defaultValue );
}
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/configuration/package.html
Index: package.html
===================================================================
<body>
<p>Resource supporting extended configuraiton management.</p>
</body>
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/DefaultServiceManager.java
Index: DefaultServiceManager.java
===================================================================
/*
* File: DefaultServiceManager.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.util.Enumeration;
import java.util.Hashtable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
/**
* Internal helper class the implements the service manager interface and
* is supplied to dynamically crerated componets during service lifecyle
* pipeline processing.
*/
class DefaultServiceManager implements ServiceManager
{
/**
* Hashtable containing service providers keyed by role name.
* The manager use the providers in this table to aquire services
* in response to <code>lookup</code> invocations. Provider
* types fall into one of the following three catagories:
*
* <table>
* <tr><td><b>Policy</b></td><td><b>Description</b></td><tr>
* <tr><td>SINGLETON_LIFETIME_POLICY</td><td>
* Service of the type singleton are distinguished by the fact
* that they do not inherit from Pool or Transient. The singleton
* provider object is a reference to the singleton service and is
* return directly by the implemetation on invocation of lookup.
* </td>
* <tr><td>POOLED_LIFETIME_POLICY</td><td>
* Pooled services implement the Pool interface. The service
* resolves lookup aquires the pooled service by invoking
* <code>checkout</code> on the pool implementation. Clients
* using pooled services are required to release services using
* the manager <code>release</code> method. The implemetation will
* attempt to locate the issuing pool and release the object on
* behalf of the client.
* </td>
* <tr><td>TRANSIENT_LIFETIME_POLICY</td><td>
* A transient provider is factory from which new instances are
* created and pipelined following a invocation of <code>lookup</code>.
* The invocing client is totally responsible for service disposal.
* </td>
*/
private Hashtable m_providers = new Hashtable();
public DefaultServiceManager( Hashtable providers ) throws Exception
{
m_providers = providers;
}
public boolean hasService( String role )
{
return (m_providers.get( role ) != null );
}
public Object lookup( String role ) throws ServiceException
{
Object provider = m_providers.get( role );
if( provider == null ) throw new ServiceException(
"Could not locate a provider for the role: " + role );
if( provider instanceof TransientProvider )
{
//
// return a transient instance
//
return ((TransientProvider)provider).create( );
}
/*
else if( provider instanceof PooledProvider )
{
//
// return a pooled service
//
return ((PooledProvider)provider).checkout( );
}
*/
else
{
//
// return a singleton service
//
return ((SingletonProvider)provider).provide( );
}
}
public void release( Object object )
{
//
// release a pooled service
//
/*
Class c = object.getClass();
Enumeration providers = m_providers.elements();
while( providers.hasMoreElements())
{
Object provider = providers.nextElement();
if( provider instanceof PooledProvider )
{
PooledProvider pool = (PooledProvider) provider;
if( pool.getBaseClass().isAssignableFrom( c ) )
{
pool.release( object );
break;
}
}
}
*/
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/DependencyInfo.java
Index: DependencyInfo.java
===================================================================
/*
* File: DependencyInfo.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import org.apache.avalon.framework.configuration.Configuration;
/**
* Abstract meta-information that describes a single dependancy that a
* <code>Serviceable</code> object may have towards other
* components.
*/
class DependencyInfo extends ServiceInfo
{
private String m_role;
/**
* Creation of a new <code<DependencyInfo</code> instance.
* @param config a configuration corresponding to a <depends>
statement
*/
public DependencyInfo( final Configuration config ) throws Exception
{
super( config.getChild("service") );
m_role = config.getChild("role").getValue();
}
/**
* Returns the role name that the component uses to lookup a
* the dependency.
* @return the dependecy role name
* @see org.apache.avalon.framework.service.ServiceManager
* @see org.apache.avalon.framework.service.Serviceable
*/
public String getRole()
{
return m_role;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/PipelineException.java
Index: PipelineException.java
===================================================================
/*
* File: PipelineException.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.StringWriter;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import org.apache.avalon.framework.CascadingException;
/**
* Thrown by an Pipeline as a result of an unexpected error
* during execution.
*
* @author mcconnell
* @version 1.0
*/
public class PipelineException extends CascadingException {
/**
* Construct a new <code>PipelineRuntimeException</code> instance with
the
* supplied message parameter and a null value for the cause exception.
*
* @param message Message summarising the exception.
*/
public PipelineException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>PipelineRuntimeException</code> instance with
the
* supplied message parameter and a supplied cause exception.
*
* @param message The detail message for this exception.
* @param cause the root cause of the exception
*/
public PipelineException( final String message, final Throwable cause )
{
super( message, cause );
}
public String toString()
{
final StringBuffer sb = new StringBuffer();
sb.append( "\n=================================================" );
sb.append( "\nException: " + this.getClass().getName() + ", " +
getMessage());
if( this.getCause() != null ) appendCause( sb, this.getCause() );
sb.append( "\n=================================================" );
return sb.toString();
}
private void appendCause( StringBuffer buffer, Throwable cause )
{
if( cause == null ) return;
buffer.append( "\nCause: " + cause.getClass().getName()
+ ", " + cause.getMessage() );
if( cause.getCause() != null )
{
appendCause( buffer, cause.getCause() );
}
else
{
buffer.append(
"\n-------------------------------------------------" );
String[] stack = captureStackTrace( cause );
for( int i=0; i<stack.length; i++ )
{
buffer.append( "\n" + stack[i] );
}
}
}
private static String[] captureStackTrace( final Throwable throwable )
{
final StringWriter sw = new StringWriter();
throwable.printStackTrace( new PrintWriter( sw, true ) );
return splitString( sw.toString(), "\n" );
}
/**
* Splits the string on every token into an array of stack frames.
*
* @param string the string
* @param onToken the token
* @return the resultant array
* @deprecated This is an internal utility method that should not be used
*/
private static String[] splitString( final String string, final String
onToken )
{
final StringTokenizer tokenizer = new StringTokenizer( string,
onToken );
final String[] result = new String[ tokenizer.countTokens() ];
for( int i = 0; i < result.length; i++ )
{
result[ i ] = tokenizer.nextToken();
}
return result;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/PipelineRuntimeException.java
Index: PipelineRuntimeException.java
===================================================================
/*
* File: PipelineRuntimeException.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.StringWriter;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import org.apache.avalon.framework.CascadingRuntimeException;
/**
* Thrown by an Pipeline as a result of an unexpected runtime error
* during execution.
*
* @author mcconnell
* @version 1.0
*/
public class PipelineRuntimeException extends CascadingRuntimeException {
/**
* Construct a new <code>PipelineRuntimeException</code> instance with
the
* supplied message parameter and a null value for the cause exception.
*
* @param message Message summarising the exception.
*/
public PipelineRuntimeException( final String message )
{
this( message, null );
}
/**
* Construct a new <code>PipelineRuntimeException</code> instance with
the
* supplied message parameter and a supplied cause exception.
*
* @param message The detail message for this exception.
* @param cause the root cause of the exception
*/
public PipelineRuntimeException( final String message, final Throwable
cause )
{
super( message, cause );
}
public String toString()
{
final StringBuffer sb = new StringBuffer();
sb.append( "\n=================================================" );
sb.append( "\nException: " + this.getClass().getName() + ", " +
getMessage());
if( this.getCause() != null ) appendCause( sb, this.getCause() );
sb.append( "\n=================================================" );
return sb.toString();
}
private void appendCause( StringBuffer buffer, Throwable cause )
{
if( cause == null ) return;
buffer.append( "\nCause: " + cause.getClass().getName()
+ ", " + cause.getMessage() );
if( cause.getCause() != null )
{
appendCause( buffer, cause.getCause() );
}
else
{
buffer.append(
"\n-------------------------------------------------" );
String[] stack = captureStackTrace( cause );
for( int i=0; i<stack.length; i++ )
{
buffer.append( "\n" + stack[i] );
}
}
}
private static String[] captureStackTrace( final Throwable throwable )
{
final StringWriter sw = new StringWriter();
throwable.printStackTrace( new PrintWriter( sw, true ) );
return splitString( sw.toString(), "\n" );
}
/**
* Splits the string on every token into an array of stack frames.
*
* @param string the string
* @param onToken the token
* @return the resultant array
* @deprecated This is an internal utility method that should not be used
*/
private static String[] splitString( final String string, final String
onToken )
{
final StringTokenizer tokenizer = new StringTokenizer( string,
onToken );
final String[] result = new String[ tokenizer.countTokens() ];
for( int i = 0; i < result.length; i++ )
{
result[ i ] = tokenizer.nextToken();
}
return result;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceContext.java
Index: ServiceContext.java
===================================================================
/*
* File: ServiceContext.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.File;
import org.apache.avalon.phoenix.BlockContext;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.context.DefaultContext;
/**
* ServiceContext context object to hold command line arguments and
* base directory that is supplied to a <code>Contextualizable</code>
* component.
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
*/
public class ServiceContext extends DefaultContext implements BlockContext
{
public static final String ARGS_KEY = "ARGS";
public static final String BASE_DIRECTORY_KEY = "APP_DIR";
private String[] m_args;
private File m_root;
private String m_name;
private Logger m_logger;
public ServiceContext( String[] args, File base, String name )
{
m_args = args;
m_root = base;
m_name = name;
super.put( ARGS_KEY, m_args );
super.put( BASE_DIRECTORY_KEY, m_root );
}
public String[] getArgs()
{
return m_args;
}
public File getBaseDirectory()
{
return m_root;
}
public Logger getLogger( String name )
{
throw new RuntimeException("Not implemented.");
}
public String getName()
{
return m_name;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceFactory.java
Index: ServiceFactory.java
===================================================================
/*
* File: ServiceFactory.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.File;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.AvalonFormatter;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
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.excalibur.configuration.CascadingConfiguration;
/**
*
*/
class ServiceFactory extends AbstractLogEnabled implements Disposable
{
private Hierarchy m_hierarchy;
private ServiceRegistry m_registry;
private Hashtable m_table = new Hashtable();
private Hashtable m_pools = new Hashtable();
private Hashtable m_singletons = new Hashtable();
private Hashtable m_transients = new Hashtable();
private File m_root;
private boolean m_verbose;
private Hashtable m_services = new Hashtable();
private Hashtable m_lookup = new Hashtable();
public ServiceFactory( Hierarchy hierarchy, Configuration config, File
base, boolean verbose ) throws Exception
{
m_hierarchy = hierarchy;
m_registry = new ServiceRegistry( verbose );
m_table = initalizeBlockConfigurations( config );
m_root = base;
m_verbose = verbose;
}
public void enableLogging( Logger logger )
{
super.enableLogging( logger );
m_registry.enableLogging( logger.getChildLogger("registry") );
}
/**
* Populates the set of available services based on a supplied
* vector of jar files.
* @param list a list of jar files
*/
public void register( Vector list ) throws PipelineException
{
m_registry.register( list );
}
public void validate( UnitInfo info ) throws Exception
{
DependencyInfo[] dependencies = info.getDependencies();
for( int i=0; i<dependencies.length; i++ )
{
ServiceInfo d = dependencies[i];
if( m_registry.lookup( d ) == null ) throw new Exception(
"Could not resolve dependent service " +
d.getInterface().getName()
+ " for block " + info.getClassName() );
}
}
private ServiceManager createServiceManager( DependencyInfo[]
dependencies ) throws ServiceException
{
Hashtable providers = new Hashtable();
try
{
for( int i=0; i<dependencies.length; i++ )
{
DependencyInfo info = dependencies[i];
providers.put( info.getRole(), getProvider( info ));
}
return new DefaultServiceManager( providers );
}
catch( Throwable e )
{
final String error = "Unexpected exception while attempting to
create a ServiceManager.";
throw new ServiceException( error, e );
}
}
private Object getProvider( DependencyInfo info ) throws Exception
{
UnitInfo block_info = m_registry.lookup( info );
//
// Try to establish the type of object by the interface it implements.
//
Object provider = null;
Class provider_class = block_info.getBaseClass();
//
// Resolve the provider based on meta-infomation in the .xinfo file
// which will result in a transient service if no other info
available.
//
int policy = block_info.getPolicy();
switch( policy )
{
case UnitInfo.SINGLETON_LIFETIME_POLICY :
//
// return a singleton instance
//
provider = m_singletons.get( provider_class );
if( provider == null )
{
if( m_verbose ) if( getLogger().isDebugEnabled() )
getLogger().debug(
"Creating singleton provider for :" +
provider_class.getName());
// create and pipeline the singleton instance and
// add it to the list of singletons
Object object = pipeline( block_info, info.getRole() );
provider = new SingletonProvider( object, info.getRole() );
m_singletons.put( provider_class, provider );
}
return provider;
case UnitInfo.POOLED_LIFETIME_POLICY :
final String error = "Cannot provide a default provider for a
pool at this time.";
throw new RuntimeException( error );
default :
//
// UnitInfo.TRANSIENT_LIFETIME_POLICY :
// new service instances are always created on invocation of
// a service lookup
//
provider = m_transients.get( provider_class );
if( provider == null )
{
if( m_verbose ) if( getLogger().isDebugEnabled() )
getLogger().debug(
"Creating transient provider for :" +
provider_class.getName());
// create and pipeline the singleton instance and
// add it to the list of singletons
provider = new TransientProvider( this, block_info,
info.getRole() );
m_transients.put( provider_class, provider );
}
return provider;
}
}
public Object pipeline( UnitInfo info, String role ) throws Exception
{
//
// create and pipeline the new instance
//
Object m_object;
try
{
m_object = info.getBaseClass().newInstance();
}
catch( Throwable e )
{
final String error = "Failed to instantiate an object: ";
throw new PipelineException( error +
info.getBaseClass().getName(), e );
}
if( m_verbose ) if( getLogger().isDebugEnabled() ) getLogger().debug(
"pipeline for role: " + role + ", implementation: " +
m_object.getClass().getName() );
//
// assign a logging channel
//
if( m_object instanceof LogEnabled ) try
{
Logger logger = new LogKitLogger( m_hierarchy.getLoggerFor( role
) );
if( m_verbose ) getLogger().debug( "applying logger to " + role );
((LogEnabled)m_object).enableLogging( logger );
}
catch( Throwable e )
{
final String error = "Failed to assign a logger channel.";
throw new PipelineException( error, e );
}
//
// configure the object
//
if( m_object instanceof Configurable ) try
{
if( m_verbose ) getLogger().debug( role + " configuration" );
Configuration defaults = info.getDefaultConfiguration();
Configuration primary = getConfigurationForClass(
info.getClassName() );
((Configurable)m_object).configure( new CascadingConfiguration(
primary, defaults ));
}
catch( Throwable e )
{
final String error = "Failed to configure an object.";
throw new PipelineException( error, e );
}
else if( m_object instanceof Parameterizable ) try
{
if( m_verbose ) getLogger().debug( role + " parameterization" );
((Parameterizable)m_object).parameterize(
Parameters.fromConfiguration( getConfigurationForClass(
info.getClassName() ) ) );
}
catch( Throwable e )
{
final String error = "Failed to parameterize an object.";
throw new PipelineException( error, e );
}
//
// contextualize the server
// [need to update this to handle an args sequence]
//
if( m_object instanceof Contextualizable ) try
{
if( m_verbose ) getLogger().debug( role + " contextualization" );
Context context = new ServiceContext(
new String[0], m_root, info.getClassName() );
((Contextualizable)m_object).contextualize( context );
}
catch( Throwable e )
{
final String error = "Failed to contextualize the object.";
throw new PipelineException( error, e );
}
//
// get the blocks required to support the dependencies
//
if( m_object instanceof Serviceable ) try
{
if( m_verbose ) getLogger().debug( role + " service composition"
);
DependencyInfo[] dependencies = info.getDependencies();
ServiceManager manager = createServiceManager( dependencies );
((Serviceable)m_object).service( manager );
}
catch( Throwable e )
{
final String error = "Failed to service the object.";
throw new PipelineException( error, e );
}
else if( m_object instanceof Composable ) try
{
if( m_verbose ) getLogger().debug( role + " composition" );
DefaultComponentManager manager = new DefaultComponentManager();
DependencyInfo[] dependencies = info.getDependencies();
for( int i=0; i<dependencies.length; i++ )
{
DependencyInfo dependency = dependencies[i];
String dependency_role = dependency.getRole();
UnitInfo block_info = m_registry.lookup( dependency );
Object object = pipeline( block_info, dependency_role );
manager.put( dependency_role, (Component) object );
}
((Composable)m_object).compose( manager );
}
catch( Throwable e )
{
final String error = "Failed to compose the object.";
throw new PipelineException( error, e );
}
//
// initialize the object
//
if( m_object instanceof Initializable ) try
{
if( m_verbose ) getLogger().debug( role + " initilization" );
((Initializable)m_object).initialize();
}
catch( Throwable e )
{
final String error = "Failed to initilize the object.";
throw new PipelineException( error, e );
}
//
// start the object
//
if( m_object instanceof Startable ) try
{
if( m_verbose ) getLogger().debug( "starting " + role );
((Startable)m_object).start();
}
catch( Throwable e )
{
final String error = "Failed to start the service.";
throw new PipelineException( error, e );
}
return m_object;
}
/**
* Notification byb the controlling application to dispose of the
* service factory.
*/
public void dispose()
{
//
// dispose of all of the service pools
//
if( m_verbose ) if( getLogger().isDebugEnabled() ) getLogger().debug(
"pool disposal (" + m_pools.size() + ")");
Enumeration pools = m_pools.elements();
while( pools.hasMoreElements() )
{
Object pool = pools.nextElement();
if( pool instanceof Disposable )
{
try
{
((Disposable)pool).dispose();
}
catch( Throwable e )
{
final String warning = "Ignoring exception while invoking
pool disposal.";
if( getLogger().isWarnEnabled() ) getLogger().warn(
warning, e );
}
}
}
//
// dispose of all of the service singletons
//
if( m_verbose ) if( getLogger().isDebugEnabled() ) getLogger().debug(
"singleton disposal (" + m_singletons.size() + ")");
Enumeration singletons = m_singletons.elements();
while( singletons.hasMoreElements() )
{
Object singleton = singletons.nextElement();
if( singleton instanceof Disposable )
{
try
{
((Disposable)singleton).dispose();
}
catch( Throwable e )
{
final String warning = "Ignoring exception while invoking
singleton provider disposal.";
if( getLogger().isWarnEnabled() ) getLogger().warn(
warning, e );
}
}
}
//
// dispose of all of the transient service providers
//
if( m_verbose ) if( getLogger().isDebugEnabled() ) getLogger().debug(
"transient disposal (" + m_transients.size() + ")");
Enumeration transients = m_transients.elements();
while( transients.hasMoreElements() )
{
Object object = transients.nextElement();
if( object instanceof Disposable )
{
try
{
((Disposable)object).dispose();
}
catch( Throwable e )
{
final String warning = "Ignoring exception while invoking
transient provider disposal.";
if( getLogger().isWarnEnabled() ) getLogger().warn(
warning, e );
}
}
}
}
//==========================================================
// configuration
//==========================================================
/**
* Creates a hashtable of configurations keyed by the block implmentation
* class name. The configuration file is ssumed to in the following form.
* <pre>
* <block class="org.apache.demo.MyFirstBlock">
* <any-child value="red"/>
* </block>
*
* <k class="org.apache.demo.MySecondBlock"/>
* </pre>
*/
private Hashtable initalizeBlockConfigurations( Configuration config )
throws ConfigurationException
{
Hashtable configs = new Hashtable();
Configuration[] blocks = config.getChildren("block");
for( int i=0; i<blocks.length; i++ )
{
final String key = blocks[i].getAttribute("class");
configs.put( key, blocks[i] );
}
return configs;
}
private Configuration getConfigurationForClass( String name )
{
Configuration config = (Configuration) m_table.get( name );
if( config != null ) return config;
return new DefaultConfiguration( name, null );
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceInfo.java
Index: ServiceInfo.java
===================================================================
/*
* File: ServiceInfo.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
/**
* Meta-information about a particular <code>service</code> exposed by a
component.
*/
class ServiceInfo
{
private Class m_interface;
private Version m_version;
/**
* Creation of a new <code>ServiceInfo</code> instance.
*/
public ServiceInfo( Configuration config ) throws Exception
{
ClassLoader loader = Thread.currentThread().getContextClassLoader( );
m_interface = loader.loadClass( config.getAttribute("name") );
m_version = Version.getVersion( config.getAttribute("version") );
}
/**
* Equality test.
* @return TRUE if this instance is equal to the supplied instance, where
* equality is derived from equivalent interface values and versions.
*/
public boolean equals( Object object )
{
if( object instanceof ServiceInfo ) return equals( (ServiceInfo)
object );
return false;
}
/**
* Equality test.
* @return TRUE if this instance is equal to the supplied instance, where
* equality is derived from equivalent interface values and versions.
*/
public boolean equals( ServiceInfo other )
{
if( !other.getInterface().isAssignableFrom( m_interface ) ) return
false;
return m_version.equals( other.getVersion() );
}
/**
* Returns the class representing the service interface.
* @return the service interface
*/
public Class getInterface()
{
return m_interface;
}
/**
* Returns the service version.
* @return the service version
*/
public Version getVersion()
{
return m_version;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceLoader.java
Index: ServiceLoader.java
===================================================================
/*
* File: ServiceLoader.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.util.jar.JarFile;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.AvalonFormatter;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.activity.Disposable;
/**
* A service loader that loads a target class, manages full component
lifecycle
* processing for the target and dependent services, and service
decommissioning.
*
* <p><table border="1" cellpadding="3" cellspacing="0" width="100%">
* <tr bgcolor="#ccccff">
* <td colspan="2"><b>Pipeline Lifecycle Phases</b></td>
* <tr><td width="20%"><b>Phase</b></td><td><b>Description</b></td></tr>
* <tr>
* <td width="20%" valign="top">Configurable</td>
* <td>
* The configuration phase supplies static information to the pipeline
processor
* that may be used to configure target and supporting services. During the
loading
* of a component, the pipline processor will attempt to locate a block
configuration
* based on the class name of the block. If there is no configuration
matching the
* class name an empty configuration will be supplied to the component or a
component
* the the target component is depedant on (assuming the component in
question
* implements the Configurable interface).
*
* <pre>
* <config>
*
* <block class="com.magic.DirectoryBlock">
* <-- block specific content -->
* </block>
*
* <block class="com.magic.ActivatorBlock">
* <-- block specific content -->
* </block>
*
* </config>
* </pre>
* </td></tr>
* <tr>
* <td width="20%" valign="top">Contextualizable</td>
* <td>
* The contextualization phase hadles the capture of runtime context
information
* needed by the pipeline processor. This information must be provided in
the
* for of a <code>ServiceLoaderContext</code> otherwise the contextualize
method will
* throw an exception. The following information is provided by the
* <code>ServiceLoaderContext</code>:
* <p><table border="0" cellpadding="3" cellspacing="0" width="100%">
* <tr>
* <td width="20%" valign="top"><code>ARGS_KEY</code></td>
* <td>
* Contains the command line arguments as a <code>String[]</code>.
* </td></tr>
* <tr>
* <td width="20%" valign="top"><code>BASE_DIRECTORY_KEY</code></td>
* <td>
* Contains the application base directory <code>File</code>.
* </td></tr>
* <tr>
* <td width="20%" valign="top"><code>TARGET_KEY</code></td>
* <td>
* Contains the name of the target class to be instantiated.
* </td></tr>
* <tr>
* <td width="20%" valign="top"><code>INCLUDES_KEY</code></td>
* <td>
* Contains an array of jar files that will be added to the pipeline
classloader.
* Jar files included in the array will be checked for block manifest
entries. If
* block entries exist that will be registered as potetentially available
services
* that may be instantiated during the recursive dependecy resolution
process.
* </td></tr>
* <tr>
* <td width="20%" valign="top"><code>CONFIGURATION_FILE_KEY</code></td>
* <td>
* A <code>File</code> instance that may or may not exist. If the file exists
and is
* confiugration, it will be used as the base configuration reference when
looking up
* service configuration details. The default behaviour is to look for a
file named
* "config.xml" in the user's working directory.
* </td></tr>
* <tr>
* <td width="20%" valign="top"><code>DISPOSAL_POLICY_KEY</code></td>
* <td>
* A <code>Boolean</code> value that is applied on completionof the startup
of a
* <code>Startable</code> component. If the value TRUE, the component is
stopped
* and disposed of (including termination of all dependencies) immediately
following
* startup. This policy only applies to <code>Startable</code> components.
Setting
* policy value to FALSE ensures that the component can respond as a server.
Non
* <code>Startable</code> target component are immediately terminated
(providing a
* useful for component testing during development cycles).
* </td></tr>
* <td width="20%" valign="top"><code>LOGGING_PRIORITY_KEY</code></td>
* <td>
* Contains the logging priority to be applied during the pipeline session.
* </td></tr>
* <td width="20%" valign="top"><code>VERBOSE_POLICY_KEY</code></td>
* <td>
* If this value is TRUE, debug logging entries from the pipeline processor
will be
* if the overall logging priority permits this. If FALSE (the default), the
logging
* entires generated by the pipeline processor will be limited to WARN,
ERROR,
* and FATAL_ERROR.
* </td></tr>
* </table>
*
* </td></tr>
* <tr><td width="20%">Initalizable</td>
* <td>
* The initilization phase handles the creation of a new instance of the
supplied
* target class, resolves any service dependencies, and runs the instance
through
* the lifecycle pipeline.
* </td></tr>
* <tr><td width="20%" valign="top">Disposable</td>
* <td>
* Cleanup and disposal of state members following termination and diposal of
* all current components.
* </td></tr>
* </table>
*/
public class ServiceLoader extends AbstractLogEnabled
implements Configurable, Contextualizable, Initializable, Disposable
{
private static final String DEFAULT_FORMAT = "[%7.7{priority}]
(%{category}): %{message}\\n%{throwable}";
private static OutputStream m_out = System.out;
private String[] m_args;
private PipelineClassLoader m_classloader;
private Priority m_priority = Priority.INFO;
private String m_target;
private Object m_object;
private File[] m_includes;
private boolean m_policy = true;
private boolean m_verbose = false;
private boolean m_terminated = false;
private boolean m_disposed = false;
private ServiceFactory m_factory;
private Configuration m_config;
/**
* Command line entry point supporting establishment and initalization of
a service
* loader instance with a supplied target component and supporting
services.
*
* <p><strong>java -jar form</strong></p>
* <p>Execution using java -jar pattern requires the presence
* of the following files under the same directory:</p>
* <ul>
* <li><code>merlin.jar</code>
* <li><code>avalon-framework.jar</code>
* <li><code>logkit.jar</code>
* </ul>
* <p>An example command line is shown below:</p>
* <pre>
* $ java -jar <strong>merlin.jar</strong> <supporting-jar-files>
* -target <class-name>
* </pre>
* <p><strong>java -classpath form</strong></p>
* <p>Execution using java -classpath pattern requires the inclusions
* of the pipeline, framework and logkit jar files in the classpath
* statement.</p>
* <p>An example command line is shown below:</p>
* <pre>
* $ java -classpath
<strong>merlin.jar;avalon-framework.jar;logkit.jar</strong>
* org.apache.avalon.excalibur.service.ServiceLoader
* <supporting-jar-files> -target <class-name>
* </pre>
* </ul>
*
* <p><table border="1" cellpadding="3" cellspacing="0" width="100%">
* <tr bgcolor="#ccccff">
* <td colspan="2"><b>Command Line Parameters and Arguments</b></td>
* <tr><td
width="20%"><b>Parameter</b></td><td><b>Description</b></td></tr>
* <tr>
* <td width="20%" valign="top"><code>-target
<class-name></code></td>
* <td>
* <p>The class to instantiate. If the class exposes any Avalon lifecycle
interface
* (such as <code>Configurable</code>, <code>Contextualizable</code>,
<code>Serviceable</code>,
* <code>Initializable</code>, <code>Startable</code>, or
<code>Disposable</code>, the
* pipeline will automate lifecycle processing and termination.
* </p>
* </td></tr>
* <tr>
* <td width="20%"
valign="top"><code><supporting-jar-files></code></td>
* <td>
* <p>A list of space seperated jar files that will be added to the
pipeline
* as supporting classes and components. Any jar file included in the list
* that contains an Avalon <code>Block</code> manifest will be registered
as
* an available service when resolving component dependecies.</p>
* </td></tr>
* <tr><td width="20%"><code>-verbose <boolean></code></td>
* <td>
* <p>A value of <code>true</code> will force debug level logging of the
actual pipeline
* processor. A value of <code>false</code> will disable pipeline debug
priority logging.
* Visibility of logging inffomration is dependent on the level supplied
under the
* <code>priority</code parameter.</p>
* </td></tr>
* <tr><td width="20%" valign="top"><code>-priority
<priority></code></td>
* <td>
* <p>Declaration of the logging priority to use during pipeline
execution. Valid values
* include FATAL_ERROR, ERROR, WARN, INFO, and DEBUG. </p>
* </td></tr>
* <tr><td width="20%" valign="top"><code>-dispose
<boolean></code></td>
* <td>
* If the target component is <code>Startable</code>, and the dispose
argument is <code>FALSE</code> the
* component will be treated as a server and will continue to run
following initialization.
* Otherwise, the component will be disposed of.
* </td></tr>
* <tr><td width="20%" valign="top"><code>-configuration
<file-path></code></td>
* <td>
* Optional parameter naming a file to be used as the configuration source.
* </td></tr>
* </table>
*
* @param args a array of <code>String</code> argument values passed under
the command line.
*/
public static void main( String[] args )
{
ServiceLoader pipeline = null;
try
{
CLI cli = new CLI( args );
pipeline = new ServiceLoader();
ServiceLoaderContext context = cli.getContext();
File path = cli.getConfigurationPath();
Configuration config = new DefaultConfiguration("-", null );
if( path != null ) config = getRuntimeConfiguration( path );
pipeline.configure( config );
pipeline.contextualize( context );
pipeline.initialize();
}
catch( IllegalParameterException ipe )
{
System.err.println( ipe.getMessage() );
}
catch( PipelineException e )
{
final String error = "Service loader processing exception.";
System.err.println( error );
System.err.println( e );
}
catch( PipelineRuntimeException e )
{
final String error = "Service loader runtime exception.";
System.err.println( error );
System.err.println( e );
}
catch( Throwable e )
{
final String error = "Unexpected service loader exception.";
System.err.println( error );
e.printStackTrace();
}
finally
{
if( pipeline != null )
{
pipeline.dispose();
}
}
}
private boolean getVerbose()
{
return m_verbose;
}
/**
* Configuration of the pipeline.
*/
public void configure( Configuration config ) throws
ConfigurationException
{
m_config = config;
}
/**
* Contextualization of the pipeline including the supply of command-line
* arguments, include files, target class, and related execution policies.
* @see ServiceLoaderContext
* @param context the pipeline context
* @exception ContextException if the supplied context is not an instance
* of ServiceLoaderContext, or if an internal error occurs while
resolving
* context information.
*/
public void contextualize( Context context ) throws ContextException
{
try
{
ServiceLoaderContext c = (ServiceLoaderContext) context;
m_includes = c.getIncludes();
m_verbose = c.getVerbose();
m_priority = c.getLoggingPriority();
m_policy = c.getDisposalPolicy();
m_target = c.getTarget();
}
catch( Throwable e )
{
final String error = "Unexpected error while reslving pipeline
context.";
throw new ContextException( error, e );
}
}
/**
* Start the pipeline and handle any errors arrising from loader execution.
*/
public void initialize() throws PipelineException
{
if( m_target == null ) throw new PipelineException(
"The pipeline task required attribute 'target' has not been not
supplied.");
try
{
Hierarchy hierarchy = createBootstrapLogger();
Logger logger = new LogKitLogger( hierarchy.getLoggerFor(
"loader" ) );
if( getLogger() == null ) super.enableLogging( logger );
if( m_classloader == null ) m_classloader = createClassloader();
m_factory = new ServiceFactory( hierarchy, m_config,
new File( System.getProperty("user.dir") ), getVerbose() );
m_factory.enableLogging( getLogger().getChildLogger("factory") );
}
catch( Throwable e )
{
final String error = "Service loader validation error.";
getLogger().error( error, e );
return;
}
try
{
process();
}
catch( PipelineException e )
{
final String error = "Service loader processing exception.";
getLogger().error( error );
}
catch( PipelineRuntimeException e )
{
final String error = "Service loader runtime exception.";
getLogger().error( error );
}
catch( Throwable e )
{
final String error = "Unexpected pipeline exception.";
getLogger().error( error, e );
}
finally
{
if( m_policy )
{
if( m_object != null ) terminate();
dispose();
return;
}
}
}
/**
* Initates execution of the loading of supporting services derived from
a
* target.
*/
private void process( ) throws PipelineException
{
//
// add the included jar files to the classloader
//
Vector list = new Vector();
Vector stack = new Vector();
for (int i=0; i<m_includes.length; i++)
{
File target = m_includes[i];
stack.add( target );
list.add( target );
}
load( stack );
// build the registry of available services
try
{
m_factory.register( list );
}
catch( Throwable e )
{
final String error = "Service loader exception encounter while
preparing services.";
throw new PipelineException( error, e );
}
//
// create an instance of the target and if verify that we can in fact
build a
// service manager if needed
//
Class target;
UnitInfo info;
try
{
target = m_classloader.loadClass( m_target );
}
catch( Throwable e )
{
final String error = "Could not load target class: " + m_target;
throw new PipelineException( error , e );
}
try
{
info = ServiceRegistry.createUnitInfo( target );
if( getVerbose() ) if( getLogger().isDebugEnabled() )
getLogger().debug( "validating target\n" + info );
try
{
m_factory.validate( info );
}
catch( Throwable e )
{
final String error = "Could not resolve a valid dependency
solution for ";
throw new CascadingException( error + info.getClassName(), e
);
}
}
catch( Throwable e )
{
final String error = "Service loader exception encounter while
preparing services.";
throw new PipelineException( error, e );
}
//
// process the target
//
try
{
m_object = m_factory.pipeline( info, "target" );
}
catch( Throwable e )
{
final String error = "Service loader exception encounter during
target execution.";
throw new PipelineException( error, e );
}
//
// add a shutdown hook so we can stop services and target and invoke
disposal
//
Runtime.getRuntime().addShutdownHook(
new Thread()
{
public void run()
{
terminate();
dispose();
}
}
);
}
/**
* Run the termination lifecycle actions on the primary object.
*/
private void terminate( )
{
if( m_terminated ) return;
m_terminated = true;
if( m_object == null ) return;
if( getVerbose() ) if( getLogger().isDebugEnabled() )
getLogger().debug(
"terminating " + m_object.getClass().getName() );
if( m_object instanceof Startable )
{
try
{
((Startable)m_object).stop();
}
catch( Throwable e )
{
final String warning = "Ignoring error while stopping
target.";
if( getLogger().isWarnEnabled() ) getLogger().warn( warning,
e );
}
}
if( m_object instanceof Disposable )
{
try
{
((Disposable)m_object).dispose();
}
catch( Throwable e )
{
final String warning = "Ignoring error while disposing of
target.";
if( getLogger().isWarnEnabled() ) getLogger().warn( warning,
e );
}
}
}
/**
* Disposal of the pipeline and release of all resources.
*/
public void dispose()
{
if( m_disposed ) return;
if( !m_terminated ) try
{
terminate();
}
catch( Throwable e )
{
// ignore and continue
}
m_disposed = true;
if( getVerbose() ) if( getLogger().isDebugEnabled() )
getLogger().debug( "loader disposal" );
if( m_factory instanceof Disposable )
{
try
{
((Disposable)m_factory).dispose();
}
catch( Throwable e )
{
final String warning = "Ignoring error while disposing of
service factory.";
getLogger().warn( warning, e );
}
}
}
//==========================================================
// classloader
//==========================================================
private PipelineClassLoader createClassloader()
{
try
{
PipelineClassLoader loader = new PipelineClassLoader();
Thread.currentThread().setContextClassLoader( loader );
return loader;
}
catch( Throwable e )
{
final String error = "Failed to instantial a classloader.";
throw new CascadingRuntimeException( error, e );
}
}
class PipelineClassLoader extends URLClassLoader
{
PipelineClassLoader( )
{
super( new URL[0], Thread.currentThread().getContextClassLoader()
);
}
protected void addURL( URL url )
{
try
{
URL jarURL = new URL("jar:" + url.toString() + "!/");
super.addURL( jarURL );
}
catch( Throwable e )
{
throw new CascadingRuntimeException(
"Unexpected error while attempting to add classloader URL:
" + url, e );
}
}
protected Class loadClass( String name, boolean resolve ) throws
ClassNotFoundException
{
return super.loadClass( name, resolve );
}
}
/**
* Load the supplied jar files under the pipeline classloader.
* For each entry in the stack, try to load it and
* if sucessfull, remove it from the stack - on completion
* the stack should be less than its original size - recursivly
* invoke load until the stack is empty.
* @param stack a <code>Vecor</code> containing a sequence of jar files
* to be added to the classloader.
*/
private void load( Vector stack )
{
int size = stack.size();
Hashtable errors = new Hashtable();
Enumeration enum = stack.elements();
while( enum.hasMoreElements() )
{
File target = (File) enum.nextElement();
try
{
m_classloader.addURL( target.toURL() );
if( getVerbose() ) getLogger().debug( "Loaded file: " +
target );
stack.remove( target );
}
catch( Throwable error )
{
errors.put( target, error );
}
}
if( stack.size() == 0 ) return;
if( stack.size() < size )
{
load( stack );
}
else
{
Enumeration keys = errors.keys();
getLogger().error("Load error count = " + errors.size() );
while( keys.hasMoreElements() )
{
File key = (File) keys.nextElement();
getLogger().error(
"Error while loading file."
+ "\n\tfile: " + key.toString(), (Throwable) errors.get(
key ) );
}
throw new RuntimeException("Unable to load file stack - see trace
for details.");
}
}
//==========================================================
// configuration
//==========================================================
/**
* Get client configuration from a file.
*/
private static Configuration getRuntimeConfiguration( final File file )
{
try
{
DefaultConfigurationBuilder builder = new
DefaultConfigurationBuilder( );
InputStream is = new FileInputStream( file );
if( is == null ) throw new Exception(
"Could not load the configuration resource \"" + file + "\"" );
return builder.build( is );
}
catch( Throwable e )
{
final String error = "Unable to create configuration.";
throw new CascadingRuntimeException( error, e );
}
}
//==========================================================
// logging
//==========================================================
private Hierarchy createBootstrapLogger()
{
try
{
Hierarchy hierarchy = Hierarchy.getDefaultHierarchy();
hierarchy.setDefaultLogTarget(
new StreamTarget( m_out, new AvalonFormatter( DEFAULT_FORMAT )
) );
hierarchy.setDefaultPriority( m_priority );
return hierarchy;
}
catch( Throwable e )
{
final String error = "Unexpected exception while creating
bootstrap logger.";
throw new CascadingRuntimeException( error, e );
}
}
//==========================================================
// command-line
//==========================================================
private static class IllegalParameterException extends Exception
{
/**
* Construct a new <code>IllegalParameterException</code> instance
with the
* supplied message parameter.
* @param message Message summarising the exception.
*/
public IllegalParameterException( final String message )
{
super( message );
}
}
private static class CLI
{
private String[] m_args = new String[0];
private Priority m_priority = Priority.INFO;
private String m_target = "";
private boolean m_policy = true;
private boolean m_verbose = false;
private File[] m_files = new File[0];
private File m_path = null;
public CLI( String[] args ) throws IllegalParameterException
{
m_args = args;
Vector vector = new Vector();
for( int i=0; i < m_args.length; i++ )
{
if( m_args[i].toLowerCase().startsWith("-tar") )
{
if( i+1 < m_args.length )
{
m_target = m_args[i+1];
i = i+1;
}
else
{
final String error = "Missing -target parameter.";
throw new RuntimeException( error );
}
}
else if( m_args[i].toLowerCase().startsWith("-conf") )
{
if( i+1 < m_args.length )
{
m_path = new File( m_args[i+1] );
i = i+1;
}
else
{
final String error = "Missing -configuration
parameter.";
throw new RuntimeException( error );
}
}
else if( m_args[i].toLowerCase().startsWith("-pri") )
{
if( i+1 < m_args.length )
{
m_priority = Priority.getPriorityForName(
m_args[i+1].toUpperCase() );
i = i+1;
}
else
{
final String error = "Missing -priority argument.";
throw new RuntimeException( error );
}
}
else if( m_args[i].toLowerCase().startsWith("-dis") )
{
if( i+1 < m_args.length )
{
m_policy = (m_args[i+1].toUpperCase().equals("TRUE"));
i = i+1;
}
else
{
final String error = "Missing -disposal argument.";
throw new RuntimeException( error );
}
}
else if( m_args[i].toLowerCase().startsWith("-ver") )
{
if( i+1 < m_args.length )
{
m_verbose =
(m_args[i+1].toUpperCase().equals("TRUE"));
i = i+1;
}
else
{
final String error = "Missing -verbose argument.";
throw new RuntimeException( error );
}
}
else if( m_args[i].startsWith("-") )
{
final String error = "Unrecognized parameter: " +
m_args[i];
throw new IllegalParameterException( error );
}
else
{
final File file = new File( m_args[i] );
if( file.exists() ) vector.add( file );
}
}
m_files = (File[]) vector.toArray( new File[0] );
}
public ServiceLoaderContext getContext()
{
return new ServiceLoaderContext( m_args, m_target, m_files,
m_policy, m_priority, m_verbose );
}
public File getConfigurationPath()
{
return m_path;
}
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceLoaderContext.java
Index: ServiceLoaderContext.java
===================================================================
/*
* File: ServiceLoaderContext.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.File;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.ContextException;
import org.apache.log.Priority;
/**
* <code>ServiceLoaderContext</code> context to hold command line arguments,
* base directory, target class name, and include files for a
* <code>ServiceLoader</code> component.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
*/
public class ServiceLoaderContext extends DefaultContext
{
/**
* Context key for command line arguments.
* @see #getArgs()
*/
public static final String ARGS_KEY = "ARGS";
/**
* Context key for the base directory.
* @see #getBaseDirectory()
*/
public static final String BASE_DIRECTORY_KEY = "APP_DIR";
/**
* Context key for the target class name.
* @see #getTarget()
*/
public static final String TARGET_KEY = "TARGET";
/**
* Context key for the set of supporting include jar files.
* @see #getIncludes()
*/
public static final String INCLUDES_KEY = "INCLUDES";
/**
* Context key for the disposal policy.
* @see #getDisposalPolicy()
*/
public static final String DISPOSAL_POLICY_KEY = "DISPOSAL.POLICY";
/**
* Context key for the logging priority.
* @see #getLoggingPriority()
*/
public static final String LOGGING_PRIORITY_KEY = "LOGGING.PRIORITY";
/**
* Context key for the verbose policy.
* @see #getVerbose()
*/
public static final String VERBOSE_POLICY_KEY = "VERBOSE.POLICY";
/**
* Creation of a new <oce>ServiceLoaderContext</code> with the supplied
* arguments.
* @param args command line arguments
* @param target class name of the target object to be loaded
* @param includes set of jar files to be added to the loader classloader
* @param disposal boolean disposal policy
* @param priority logging priority
* @param verbose policy concerning display of loader debug messages
*/
public ServiceLoaderContext( final String[] args, final String target,
final File[] includes, final boolean disposal, final Priority priority, final
boolean verbose )
{
super.put( ARGS_KEY, args );
super.put( TARGET_KEY, target );
super.put( BASE_DIRECTORY_KEY, new File(
System.getProperty("user.dir")) );
super.put( INCLUDES_KEY, includes );
super.put( DISPOSAL_POLICY_KEY, new Boolean( disposal ));
super.put( VERBOSE_POLICY_KEY, new Boolean( verbose ));
super.put( LOGGING_PRIORITY_KEY, priority );
}
/**
* Returns the command-line argument <code>String[]</code>.
* @return String[] command line arguments
*/
public String[] getArgs()
{
try
{
return (String[]) super.get( ARGS_KEY );
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving
command line arguments.";
throw new PipelineRuntimeException( error, e );
}
}
/**
* Returns the base directory as a <code>File</code>.
* @return File the base working directory
*/
public File getBaseDirectory()
{
try
{
return (File) super.get( BASE_DIRECTORY_KEY );
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving base
directory.";
throw new PipelineRuntimeException( error, e );
}
}
/**
* Returns the disposal policy to apply if the target component implements
* the <code>Startable</code> interface.
* @return boolean the target component disposal policy
*/
public boolean getDisposalPolicy()
{
try
{
return ((Boolean)super.get( DISPOSAL_POLICY_KEY )).booleanValue();
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving
disposal policy.";
throw new PipelineRuntimeException( error, e );
}
}
/**
* Class name of a target object.
* @return String the class name of the target
*/
public String getTarget()
{
try
{
return (String) super.get( TARGET_KEY );
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving
include files.";
throw new PipelineRuntimeException( error, e );
}
}
/**
* Returns the set of supporting jar files.
* @return File[] an array of jar files supporting target composition and
execution
*/
public File[] getIncludes()
{
try
{
return (File[]) super.get( INCLUDES_KEY );
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving
include files.";
throw new PipelineRuntimeException( error, e );
}
}
/**
* Returns the logging priority.
* @return Priority the logging priority to apply.
*/
public Priority getLoggingPriority()
{
try
{
return (Priority) super.get( LOGGING_PRIORITY_KEY );
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving
logging priority.";
throw new PipelineRuntimeException( error, e );
}
}
/**
* Returns the verbose policy - if true, logging entries from the pipeline
* will be inclued, otherwise, logging entries will be restricted to the
* target component.
* @return boolean the verbose policy
*/
public boolean getVerbose()
{
try
{
return ((Boolean)super.get( VERBOSE_POLICY_KEY )).booleanValue();
}
catch( ContextException e )
{
final String error = "Unexpected exception while retrieving
verbose policy.";
throw new PipelineRuntimeException( error, e );
}
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceProvider.java
Index: ServiceProvider.java
===================================================================
/*
* File: ServiceProvider.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import org.apache.avalon.framework.activity.Disposable;
/**
* <code>ServiceProvider</code> is an abstract base class to services
* factories supporting TRANSIENT, POOLED, and SINGLETON services. The
* abstract class provides the single <code>getRole</code> method that
* can be used by a <code>ServiceManager</code> implementation to identity
* a service provider for a particular role.
* A concrete <code>ServiceProvider</code> instance will typically be
* created by an implementation when constructing a
<code>ServiceManager</code>
* for a target component.
*/
abstract class ServiceProvider implements Disposable
{
private String m_role;
/**
* Creation of a new <code>ServiceProvider</code> instance based on
* a supplied role.
* @param role the role of the service provided by the provider relative
* to a <code>ServiceManager</code> that is exposing provider services.
*/
public ServiceProvider( String role )
{
m_role = role;
}
/**
* Returns the role of this provider within the scope of a
<code>ServiceManager</code>.
* @return String the role of the service provider by the provider.
*/
public String getRole()
{
return m_role;
}
/**
* Disposal of the provider and release of related resources.
*/
public void dispose()
{
m_role = null;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ServiceRegistry.java
Index: ServiceRegistry.java
===================================================================
/*
* File: ServiceRegistry.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.util.Vector;
import java.util.Iterator;
import java.util.Map;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.CascadingException;
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;
/**
* Internal class supporting registration of available services.
*/
class ServiceRegistry extends AbstractLogEnabled
{
private Vector m_repository = new Vector();
private UnitInfo[] m_block_info_set;
private Hashtable m_table;
private boolean m_verbose = false;
public ServiceRegistry( boolean verbose )
{
m_verbose = verbose;
}
public void register( UnitInfo info )
{
m_repository.add( info );
}
/**
* Populates the set of available services based on a supplied
* vector of jar files.
* @param list a list of jar files
*/
public void register( Vector list ) throws PipelineException
{
Vector registry = new Vector();
Enumeration enum = list.elements();
while( enum.hasMoreElements() )
{
File target = (File) enum.nextElement();
UnitInfo[] blocks = register( target );
if( m_verbose ) if( blocks.length > 0 ) if(
getLogger().isDebugEnabled() )
getLogger().debug(
"file: " + target + " has " + blocks.length + " block
declarations" );
}
}
/**
* Register a jar file with the registry.
* @param file the jar file to register
*
*/
public UnitInfo[] register( File target ) throws PipelineException
{
UnitInfo[] blocks = getUnitInfo( target );
for( int i=0; i<blocks.length; i++ )
{
UnitInfo info = blocks[i];
m_repository.add( info );
}
return blocks;
}
public UnitInfo lookup( ServiceInfo info )
{
Enumeration enum = m_repository.elements();
while( enum.hasMoreElements() )
{
UnitInfo block_info = (UnitInfo) enum.nextElement();
if( block_info.provides( info ) ) return block_info;
}
return null;
}
/**
* Returns an array of block infos provided by the jar file.
* @return a <code>UnitInfo[]<code> provided by the jar file
*/
private UnitInfo[] getUnitInfo( File file ) throws PipelineException
{
Vector vector = new Vector();
try
{
//
// if the file contains block declarations, then pipeline and
// blocks as a supporting service that will be provided to the
// target server
//
String[] blocks = getBlocks( file );
for( int i=0; i<blocks.length; i++ )
{
//
// get the block implementation class and check for
// dependecies - if dependencies > 0 then ignore it
// otherwise pipeline the block and add it as a
// service
//
final String path = blocks[i];
Configuration config = loadConfiguration( path + ".conf",
true );
Configuration xinfo = loadConfiguration( path + ".xinfo",
false );
if( xinfo == null ) throw new IllegalStateException(
"Could not locate <class>.xinfo resource for: " + path
);
final String classname = path.replace('/','.');
Class block =
Thread.currentThread().getContextClassLoader().loadClass( classname );
vector.add( new UnitInfo( block, xinfo, config ));
}
}
catch( Throwable e )
{
throw new CascadingRuntimeException(
"Unexpected error while attempting to load file: " + file, e );
}
return (UnitInfo[]) vector.toArray( new UnitInfo[0] );
}
/**
* Returns a single block info relative to a supplied class.
* @return a <code>UnitInfo<code> for the class.
*/
public static UnitInfo createUnitInfo( Class block ) throws
PipelineException
{
try
{
String path = block.getName().replace('.','/');
Configuration config = loadConfiguration( path + ".config", true
);
Configuration xinfo = loadConfiguration( path + ".xinfo", false );
if( xinfo == null ) xinfo = new DefaultConfiguration("", null);
return new UnitInfo( block, xinfo, config );
}
catch( Throwable e )
{
throw new CascadingRuntimeException(
"Unexpected error while attempting to resolve block info for a
class: " + block.getName(), e );
}
}
//===============================================================================
// utilities
//===============================================================================
/**
* Returns an array of <code>String</code>s corresponding to the set of
classnames
* where each classname is a declared block within the supplied jar file.
* @param file a jar file
*/
private String[] getBlocks( File file )
throws CascadingException, IllegalArgumentException
{
final Vector vector = new Vector();
try
{
JarFile jar = new JarFile( file );
Map map = jar.getManifest().getEntries();
Iterator iterator = map.keySet().iterator();
while( iterator.hasNext() )
{
String name = (String) iterator.next();
Attributes attributes = (Attributes) map.get( name );
Iterator it = attributes.keySet().iterator();
while( it.hasNext() )
{
Object entry = it.next();
if( entry.toString().equals("Avalon-Block") )
{
if( attributes.get( entry ).equals("true") )
{
vector.add(
name.substring(0,name.indexOf(".class")));
}
}
}
}
}
catch( IOException e )
{
final String error = "IO exception while attempt to read block
manifest.";
throw new CascadingException( error, e );
}
catch( Throwable e )
{
final String error = "Unexpected exception while inspecting
manifest on file: ";
throw new CascadingException( error + file, e );
}
finally
{
return (String[]) vector.toArray( new String[0] );
}
}
/**
* Returns a configuration resource form a jar file.
* @param path the package path to the resource e.g. net/osm/config.xml
* @param create if TRUE and no configuration found, return an empty
* configuration, else, return null
* @exception ConfigurationException if there is a problem
*/
private static Configuration loadConfiguration( String path, boolean
create )
throws ConfigurationException
{
try
{
DefaultConfigurationBuilder builder = new
DefaultConfigurationBuilder( );
InputStream is =
Thread.currentThread().getContextClassLoader().getResourceAsStream( path );
if( is != null ) return builder.build( is );
if( create ) return new DefaultConfiguration("-",null);
return null;
}
catch( Throwable e )
{
final String error = "Unexpected exception while attempting to
load a configuration from path: ";
throw new ConfigurationException( error, e );
}
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/SingletonProvider.java
Index: SingletonProvider.java
===================================================================
/*
* File: SingletonProvider.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import org.apache.avalon.framework.activity.Disposable;
/**
* A <code>SingletonProvider</code> is a provider of singleton services. A
* singleton service is a service that is managed by the container providing
the
* the service. The container providing the service is reposible for all
lifecycle
* actions including service decommissioning.
*/
class SingletonProvider extends ServiceProvider
{
private Object m_object;
/**
* Creation of a new <code>SingletonProvider</code>.
* @param object the singleton object to provide.
*/
public SingletonProvider( Object object, String role )
{
super( role );
m_object = object;
}
/**
* Provides a reference to a singleton service.
* @return Object the singleton service
*/
public Object provide()
{
return m_object;
}
/**
* Disposal of the provider and release of related resources.
*/
public void dispose()
{
if(( m_object != null ) && ( m_object instanceof Disposable )) try
{
((Disposable)m_object).dispose();
}
catch( Throwable anything )
{
// ignore it
}
finally
{
super.dispose();
}
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/TransientProvider.java
Index: TransientProvider.java
===================================================================
/*
* File: TransientProvider.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import org.apache.avalon.framework.CascadingRuntimeException;
/**
* A <code>TransientProvider</code> is a provider of transient services. A
* transient service is a service where total responsibility for the lifetime
* of the service rests with client aquiring the service.
*/
class TransientProvider extends ServiceProvider
{
private ServiceFactory m_factory;
private UnitInfo m_info;
private boolean m_disposed;
public TransientProvider( ServiceFactory factory, UnitInfo info, String
role )
{
super( role );
m_info = info;
m_factory = factory;
}
/**
* Create a new instance of a transient service.
* @return Object a new instance of a transient service
*/
public Object create()
{
if( m_disposed ) throw new IllegalStateException( "Transient provider
has been disposed.");
try
{
return m_factory.pipeline( m_info, super.getRole() );
}
catch( Throwable e )
{
final String error = "Unexpected error while creating transient
service.";
throw new CascadingRuntimeException( error, e );
}
}
/**
* Disposal of the provider and release of related resources.
*/
public void dispose()
{
m_disposed = true;
m_factory = null;
m_info = null;
super.dispose();
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/UnitInfo.java
Index: UnitInfo.java
===================================================================
/*
* File: UnitInfo.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service;
import java.util.Vector;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.configuration.Configuration;
/**
* Meta information about a <code>Serviceable</code> component.
*/
class UnitInfo
{
public static final int SINGLETON_LIFETIME_POLICY = 0;
public static final int POOLED_LIFETIME_POLICY = 1;
public static final int TRANSIENT_LIFETIME_POLICY = 2;
private Class m_block;
private Configuration m_xinfo;
private Configuration m_config;
private ServiceInfo[] m_services;
private DependencyInfo[] m_dependencies;
private boolean m_installed = false;
private Object m_object;
private int m_policy = SINGLETON_LIFETIME_POLICY;
/**
* Creation of a new UnitInfo based a xinfo configuration
* derived from the supplied class name.
* The UnitInfo recognises the the following structures within
* the xinfo configuration:
* <pre>
* <blockinfo>
*
* <block>
* <version>1.0</version>
* </block>
*
* <!--
* services that are offered by this block
* -->
*
* <services>
* <service name="hello.Hello" version="1.0"/>
* </services>
*
* <!--
* Implementation policy may one of the following enumerations:
* (a) SINGLETON, service is available for the lifetime of the manager
* (b) POOLED, the implementation implements Pool
* (c) TRANSIENT, manager is a factory of transient service instances
* -->
*
* <implementation policy="SINGLETON" />
*
* </blockinfo>
* </pre>
*
* @param block the implementation class
* @param the xinfo meta-information in the form of a Configuration
* @param the default component configuration
*/
public UnitInfo( Class block, Configuration xinfo, Configuration config )
throws Exception
{
m_block = block;
m_xinfo = xinfo;
m_config = config;
try
{
Configuration[] services =
xinfo.getChild("services").getChildren("service");
Vector vector = new Vector();
for( int i=0; i<services.length; i++ )
{
vector.add( new ServiceInfo( services[i] ));
}
m_services = (ServiceInfo[]) vector.toArray( new ServiceInfo[
vector.size() ] );
}
catch( Throwable e )
{
throw new CascadingException( "Could not construct service
information.", e );
}
try
{
Configuration[] dependencies =
xinfo.getChild("dependencies").getChildren("dependency");
Vector vector = new Vector();
for( int i=0; i<dependencies.length; i++ )
{
vector.add( new DependencyInfo( dependencies[i] ));
}
m_dependencies = (DependencyInfo[]) vector.toArray( new
DependencyInfo[ vector.size() ] );
}
catch( Throwable e )
{
throw new CascadingException( "Could not construct dependency
information.", e );
}
String policy =
xinfo.getChild("implementation").getAttribute("policy","TRANSIENT");
if( policy.equalsIgnoreCase( "SINGLETON" ) )
{
m_policy = SINGLETON_LIFETIME_POLICY;
}
else if( policy.equalsIgnoreCase( "POOLED" ) )
{
m_policy = POOLED_LIFETIME_POLICY;
}
else
{
m_policy = TRANSIENT_LIFETIME_POLICY;
}
}
/**
* Returns the name of the class implemenmting the service.
* @return the class name
*/
public String getClassName()
{
return m_block.getName();
}
/**
* Returns the set of services provided by the component.
* @return an array of <code>ServiceInfo</code> instance
*/
public ServiceInfo[] getServices()
{
return m_services;
}
/**
* Returns a <code>ServiceInfo</code> from the <code>UnitInfo</code>
matching
* the supplied service descriptor.
* @param info a <code>ServiceInfo</code> to locate with the
<code>UnitInfo</code> instance
* @return a <code>ServiceInfo</code> instance matching the supplied
service descriptor
*/
public ServiceInfo getService( ServiceInfo info )
{
ServiceInfo[] services = getServices();
for( int i=0; i<services.length; i++ )
{
if( services[i].equals( info )) return services[i];
}
return null;
}
/**
* Returns a <code>TRUE</code> if the supplied <code>ServiceInfo</code>
can be
* provided by the implementation.
* @param service the requested service
* @return boolean TRUE if the service is available otherwise FALSE
*/
public boolean provides( ServiceInfo service )
{
return ( getService( service ) != null );
}
/**
* Returns a array of <code>DependencyInfo</code> descriptors that detail
* the dependencies that this component has on other components.
* @return component dependencies
*/
public DependencyInfo[] getDependencies()
{
return m_dependencies;
}
/**
* Returns the implemetation policy. The value returned shall be one of
* SINGLETON_LIFETIME_POLICY, POOLED_LIFETIME_POLICY, or
TRANSIENT_LIFETIME_POLICY.
* @return implementation policy
*/
public int getPolicy()
{
return m_policy;
}
/**
* The component implementation class.
* @return the component implementation class
*/
public Class getBaseClass()
{
return m_block;
}
/**
* Return the default configuration.
* @return the default configuration
*/
public Configuration getDefaultConfiguration()
{
return m_config;
}
/**
* Returns a string representation of the descriptor.
* @return stringified representation
*/
public String toString()
{
final StringBuffer buffer = new StringBuffer();
buffer.append( " block: " + getClassName() );
ServiceInfo[] services = getServices();
for( int i=0; i<services.length; i++ )
{
buffer.append( "\n service: " +
services[i].getInterface().getName()
+ ", version: " + services[i].getVersion() );
}
DependencyInfo[] dependencies = getDependencies();
for( int i=0; i<dependencies.length; i++ )
{
buffer.append( "\n dependecy: "
+ "role: " + dependencies[i].getRole()
+ ", service: " + dependencies[i].getInterface().getName()
+ ", version: " + dependencies[i].getVersion() );
}
return buffer.toString();
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/package.html
Index: package.html
===================================================================
<body>
<p>Resource supporting the management of components using dynamic service
composition.</p>
<table border="1" cellpadding="3" cellspacing="0" width="100%">
<tr bgcolor="#ccccff">
<td colspan="2"><b>Features Summary</b></td>
<tr><td width="20%"><b>Feature</b></td>
<td><b>Description</b></td></tr>
<tr><td width="20%" valign="top">Service Composition</td>
<td>Handles automated composition of services based on declared component
dependencies.</td></tr>
<tr><td>Default Configurations</td>
<td>Provides support for configuration using component default configurations
together
with supplied configuration information using the CascadingConfiguration
model.</td></tr>
<tr><td>Mixed execution modes</td>
<td>Supports execution from the command line (main method), as a jar file, as
an Ant task,
and as an embedded component.</td></tr>
</table>
<h3>Component Creation</h3>
The pipeline class manages the creation and deployment of a target component
and dynamic
resolution of dependencies based on meta-information contained in a jar
manifest file. Entries
in the manifest file reference class names that are used to load the
component implementation
and configuration the component based on meta-information contained in .xinfo
and .conf files
of the same name as the implementation class.
<h4>The Manifest File</h4>
<p>Reusable components are published through a manifest declaration show
below. When
a jar file is supplied to the Pipeline the manifest is checked for any block
declarations.
Blocks declared within the manifest are registered by the pipeline as
potentially available
services that can be used in service dependency resolution. Each
Avalon-block declaration
in the manifest refers to a component implementation class and its associated
.xinfo file.</p>
<pre>
Manifest-Version: 1.0
Name: org/apache/DirectoryBlock.class
Avalon-Block: true
Name: org/apache/ReferralBlock.class
Avalon-Block: true
</pre>
<h4>The <classname>.xinfo File</h4>
<p>For each component declared in a manifest, the implementation establishes
the available services
and dependencies based on information contained in an <code>.xinfo</code>
file. Given a component
implementation class
<strong><code>org/apache/DirectoryBlock.class</code></strong> the
<code>Pipeline</code> processor
will attempt to locate a
<strong><code>org/apache/DirectoryBlock.xinfo</code></strong> resource in the
jar file.</P>
<pre>
<?xml version="1.0"?>
<blockinfo>
<font color="blue"><i><!--
Block version.
--></i></font>
<block>
<version>1.0</version>
</block>
<font color="blue"><i><!--
Services that are offered by the component are declared under the
services element. A services element may contain multiple service
declarations.
--></i></font>
<services>
<font color="blue"><i><!--
A service declaration includes a class name (typically an interface)
and a service version identifier. Service versions may have up to
three fiels (e.g. 1.1.3).
--></i></font>
<service name="org.apache.ReferralService" version="1.0" />
</services>
<font color="blue"><i><!--
A component declares the dependencies it has with other components
under
the dependencies element. A dependencies element may contain multiple
dependency statements.
--></i></font>
<dependencies>
<font color="blue"><i><!--
A dependency element contains the declaration of a role and a
service
that the component is dependent on. The pipeline processor will
attempt
to resolve dependencies based on registered services and
dynamically
establish and provide the dependencies via the component
Serviceable
implementation. The role name corresponds to the identifying string
that the component implementation will use to lookup a service from
a service manger during the serviceable lifecycle phase.
--></i></font>
<dependency>
<role>directory</role>
<service name="org.apache.DirectoryService"
version="1.0"/>
</dependency>
</dependencies>
<font color="blue"><i><!--
Component implementation policy may one of the following:
(a) SINGLETON, service is available for the lifetime of the manager
(b) POOLED, the implementation implements Pool (implementation pending)
(c) TRANSIENT, manager is a factory of transient service instances
--></i></font>
<implementation policy="SINGLETON" />
</blockinfo>
</pre>
<h4>The <classname>.conf File</h4>
<p>The pipeline processor provides support for the automated retrieval of
default
configurations for a component. During lifecycle processing, the pipeline
processor
will attempt to locate a configuration resource with the same path and name
as
the component implementation class. For example, for the component
<strong><code>org/apache/DirectoryBlock.class</code></strong>, the
implementation will look for
a default configuration under the resource path
<strong><code>org/apache/DirectoryBlock.conf</code></strong>.
During the configuration stage, the pipeline processor will supply the
component with
a <code>CascadingConfiguration</code> where the primary configuration is
configuration
derived from the pipeline processor configuration, and a default
configuration corresponding
to the .conf configuration.
</p>
<pre>
</body>
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/excalibur/service/ant/Load.java
Index: Load.java
===================================================================
/*
* File: Load.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2002, All Rights Reserved.
*/
package org.apache.avalon.excalibur.service.ant;
import java.io.*;
import java.io.File;
import java.util.*;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.MalformedURLException;
import java.util.jar.JarFile;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Exec;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.PumpStreamHandler;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Path;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.AvalonFormatter;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.activity.Disposable;
/**
* A service loader task. Loads a series a blocks as supporting services,
* supporting libraries, and runs a target component.</p>
*/
public class Load extends Task
{
private String[] m_args;
private Vector m_filesets = new Vector();
private String m_target;
private String m_priority;
private String m_policy = "true";
private String m_verbose = "false";
private Commandline m_cmd = new Commandline();
private Execute m_exe = new Execute(new PumpStreamHandler(System.out,
System.err));
private Path m_classpath;
/**
* Adds a set of files (nested fileset attribute).
*/
public void addFileset(FileSet set)
{
m_filesets.addElement(set);
}
public void setClasspath(Path path)
{
if (m_classpath == null)
{
m_classpath = path;
}
else
{
m_classpath.append(path);
}
}
public Path createClasspath()
{
if (m_classpath == null) m_classpath = new Path(project);
return m_classpath.createPath();
}
/**
* Sets the target class.
*/
public void setTarget( String target )
{
m_target = target;
}
/**
* Set the log priority.
*/
public void setPriority( String level )
{
m_priority = level;
}
/**
* Set the disposal policy.
* @param String boolean equivalent
*/
public void setDisposal( String policy )
{
m_policy = policy;
}
/**
* Set the disposal policy.
* @param String boolean equivalent
*/
public void setVerbose( String value )
{
m_verbose = value;
}
/**
* Performs execution as an Ant target.
*/
public void execute() throws BuildException
{
//
// add the classpath
//
if (m_classpath == null)
{
m_classpath = Path.systemClasspath;
}
else
{
m_classpath = m_classpath.concatSystemClasspath("ignore");
}
m_cmd.createArgument().setValue("-classpath");
m_cmd.createArgument().setPath(m_classpath);
Commandline toExecute = (Commandline)m_cmd.clone();
toExecute.setExecutable("java");
//
// declare the service loader class
//
toExecute.createArgument().setValue("org.apache.avalon.excalibur.service.ServiceLoader");
//
// preprocess the fileset into a vector of file arguments
//
for (int i=0; i<m_filesets.size(); i++)
{
final FileSet fs = (FileSet) m_filesets.elementAt(i);
final File base = fs.getDir( project );
final DirectoryScanner ds = fs.getDirectoryScanner(project);
final String[] files = ds.getIncludedFiles();
for( int j=0; j<files.length; j++ )
{
File target = new File( base, files[j] );
toExecute.createArgument().setValue( target.toString() );
}
}
// add the target parameter
toExecute.createArgument().setValue( "-target" );
toExecute.createArgument().setValue( m_target );
// add the priority parameter
toExecute.createArgument().setValue( "-priority");
toExecute.createArgument().setValue( m_priority );
// add the policy parameter
toExecute.createArgument().setValue( "-disposal");
toExecute.createArgument().setValue( m_policy );
// add the verbose parameter
toExecute.createArgument().setValue( "-verbose");
toExecute.createArgument().setValue( m_verbose );
try
{
m_exe.setAntRun(project);
m_exe.setWorkingDirectory( new
File(System.getProperty("user.dir")));
m_exe.setCommandline(toExecute.getCommandline());
int ret = m_exe.execute();
}
catch( Throwable e )
{
e.printStackTrace();
throw new BuildException( e.getMessage() );
}
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/phoenix/Block.java
Index: Block.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.avalon.phoenix;
import org.apache.avalon.framework.component.Component;
/**
* The main interface to implement for Applications hosted in Phoenix.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a>
*/
public interface Block
extends Component
{
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/avalon/phoenix/BlockContext.java
Index: BlockContext.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.avalon.phoenix;
import java.io.File;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.Logger;
/**
* Context via which Blocks communicate with container.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
*/
public interface BlockContext
extends Context
{
String APP_HOME_DIR = "app.home";
String NAME = "block.name";
/**
* Base directory of .sar application.
*
* TODO: Should this be getHomeDirectory() or getWorkingDirectory() or
other?
* TODO: Should a Block be able to declare it doesn't use the Filesystem?
If
* it declares this then it would be an error to call this method.
*
* @return the base directory
*/
File getBaseDirectory();
/**
* Retrieve name of block.
*
* @return the name of block
*/
String getName();
/**
* Retrieve logger coresponding to named category.
*
* TODO: Determine if this is really necessary ?
*
* @return the logger
*/
Logger getLogger( String name );
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/demo/DirectoryBlock.java
Index: DirectoryBlock.java
===================================================================
/*
* DirectoryBlock.java
*/
package org.apache.demo;
import java.io.File;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.phoenix.BlockContext;
import org.apache.avalon.phoenix.Block;
/**
* This is a minimal demonstration service that returns the number of
* files in a directory. The purpose of this class is to falidate
* pipeline dependecy management. Within that context this class
* is declared as a singleton service provider with no dependecies.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
*/
public class DirectoryBlock extends AbstractLogEnabled
implements Block, Disposable, DirectoryService
{
/**
* Returns the list of files.
* @return File[]
*/
public File[] getFiles( File file ) throws Exception
{
if( getLogger().isDebugEnabled() ) getLogger().debug("directory
count");
return file.listFiles();
}
public void dispose()
{
if( getLogger().isDebugEnabled() ) getLogger().debug("directory
disposal");
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/demo/DirectoryBlock.xinfo
Index: DirectoryBlock.xinfo
===================================================================
<?xml version="1.0"?>
<!--
File: DirectoryBlock.xinfo
License: etc/LICENSE.TXT
Copyright: Copyright (C) The Apache Software Foundation. All rights reserved.
Copyright: OSM SARL 2001-2002, All Rights Reserved.
@author Stephen McConnell
@version 1.0 12/03/2001
-->
<blockinfo>
<block>
<version>1.0</version>
</block>
<!--
services that are offered by this block
-->
<services>
<service name="org.apache.demo.DirectoryService" version="1.0"/>
</services>
<!--
Implememtatiuon policy may one of the following enumerations:
(a) SINGLETON, service is available for the lifetime of the manager
(b) POOLED, the implementation implements Pool
(c) TRANSIENT, manager is a factory of transient service instances
-->
<implementation policy="SINGLETON" />
</blockinfo>
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/demo/DirectoryService.java
Index: DirectoryService.java
===================================================================
/**
* File: DirectoryService.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2001-2002, All Rights Reserved.
*/
package org.apache.demo;
import java.io.File;
/**
* <code>DirectoryService</code>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
*/
public interface DirectoryService
{
/**
* Returns the list of files.
* @return File[]
*/
public File[] getFiles( File file ) throws Exception;
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/demo/ReferralBlock.java
Index: ReferralBlock.java
===================================================================
/*
* ExampleBlock.java
*/
package org.apache.demo;
import java.io.File;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
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.configuration.Configurable;
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.service.Serviceable;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceException;
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.phoenix.BlockContext;
import org.apache.avalon.phoenix.Block;
/**
* This is a minimal demonstration server.
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
*/
public class ReferralBlock extends AbstractLogEnabled
implements Block, Configurable, Contextualizable, Serviceable, Initializable,
Disposable, ReferralService
{
private Configuration m_configuration;
private Context m_context;
private ServiceManager m_manager;
private DirectoryService m_directory;
private boolean m_disposed = false;
//=================================================================
// Contextualizable
//=================================================================
public void contextualize( Context context ) throws ContextException
{
m_context = context;
}
//=======================================================================
// Configurable
//=======================================================================
public void configure( final Configuration config )
throws ConfigurationException
{
m_configuration = config;
}
//=================================================================
// Serviceable
//=================================================================
/**
* Pass the <code>ServiceManager</code> to the <code>Serviceable</code>.
* The <code>Serviceable</code> implementation uses the specified
* <code>ServiceManager</code> to acquire the services it needs for
* execution.
*
* @param manager The <code>ServiceManager</code> which this
* <code>Serviceable</code> uses.
*/
public void service( ServiceManager manager )
throws ServiceException
{
m_manager = manager;
}
//=======================================================================
// Initializable
//=======================================================================
public void initialize()
throws Exception
{
//
// verify current state
//
if( getLogger() == null ) throw new IllegalStateException(
"Logging channel has not been assigned.");
if( m_configuration == null ) throw new IllegalStateException(
"Configuration has not been declared.");
if( m_manager == null ) throw new IllegalStateException(
"Manager has not been declared.");
//
// do something using the directory service
//
doTest();
}
//=======================================================================
// ExampleService
//=======================================================================
public boolean doTest()
{
try
{
if( getLogger().isDebugEnabled() ) getLogger().debug("aquired
directory service");
m_directory = (DirectoryService) m_manager.lookup("directory");
if( getLogger().isDebugEnabled() ) getLogger().debug("executing
service");
File[] files = m_directory.getFiles( new File(
System.getProperty("user.dir") ));
getLogger().info( files.length + " file(s)" );
if( getLogger().isDebugEnabled() ) getLogger().debug("service
execution ok");
}
catch( Throwable e )
{
throw new CascadingRuntimeException( "zutt", e );
}
return true;
}
//=======================================================================
// Disposable
//=======================================================================
public void dispose()
{
if( m_disposed ) return;
m_disposed = true;
if( getLogger().isDebugEnabled() ) getLogger().debug("referral
disposal");
m_manager.release( m_directory );
m_configuration = null;
m_context = null;
m_manager = null;
}
}
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/demo/ReferralBlock.xinfo
Index: ReferralBlock.xinfo
===================================================================
<?xml version="1.0"?>
<!--
File: ExampleBlock.xinfo
License: etc/LICENSE.TXT
Copyright: Copyright (C) The Apache Software Foundation. All rights reserved.
Copyright: OSM SARL 2001-2002, All Rights Reserved.
@author Stephen McConnell
@version 1.0 12/03/2001
-->
<blockinfo>
<block>
<version>1.0</version>
</block>
<!--
services that are offered by this block
-->
<services>
<service name="org.apache.demo.ReferralService" version="1.0" />
</services>
<dependencies>
<dependency>
<role>directory</role>
<service name="org.apache.demo.DirectoryService" version="1.0"/>
</dependency>
</dependencies>
</blockinfo>
1.1
jakarta-avalon-apps/enterprise/tools/src/java/org/apache/demo/ReferralService.java
Index: ReferralService.java
===================================================================
/**
* File: ReferralService.java
* License: etc/LICENSE.TXT
* Copyright: Copyright (C) The Apache Software Foundation. All rights
reserved.
* Copyright: OSM SARL 2001-2002, All Rights Reserved.
*/
package org.apache.demo;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.omg.CORBA_2_3.ORB;
/**
* <code>ReferralService</code>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
*/
public interface ReferralService
{
/**
* Returns TRUE is the demo is working correctly.
* @return boolean TRUE if the test executes correctly
*/
public boolean doTest();
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>