mcconnell 2004/04/04 09:36:46
Modified: site/xdocs/event navigation.xml
site/xdocs/fortress navigation.xml
site/xdocs navigation.xml
Added: site/xdocs i18n.xml logger.xml
site/xdocs/lifecycle extension.xml fortress.xml index.xml
interfaces.xml merlin.xml navigation.xml
Removed: lifecycle/site .cvsignore LICENSE.txt gump-build.xml
project.properties project.xml
lifecycle/site/xdocs extension.xml fortress.xml index.xml
interfaces.xml merlin.xml navigation.xml
logger/xdocs index.xml navigation.xml
thread/site .cvsignore LICENSE.txt gump-build.xml
project.properties project.xml
thread/site/xdocs index.xml navigation.xml
Log:
Site updates.
Revision Changes Path
1.2 +3 -0 avalon-excalibur/site/xdocs/event/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/avalon-excalibur/site/xdocs/event/navigation.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- navigation.xml 4 Apr 2004 16:26:18 -0000 1.1
+++ navigation.xml 4 Apr 2004 16:36:45 -0000 1.2
@@ -32,6 +32,9 @@
</item>
<item name="Event" href="event/index.html"/>
<item name="I18N" href="i18n.html"/>
+ <item name="Logger" href="logger.html"/>
+ <item name="Lifecycle" href="lifecycle/index.html"/>
+ <item name="Thread" href="thread.html"/>
</menu>
<menu name="Resources">
1.2 +3 -0 avalon-excalibur/site/xdocs/fortress/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/avalon-excalibur/site/xdocs/fortress/navigation.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- navigation.xml 4 Apr 2004 16:26:18 -0000 1.1
+++ navigation.xml 4 Apr 2004 16:36:46 -0000 1.2
@@ -33,6 +33,9 @@
<item name="Design Notes" href="fortress/design-notes.html"/>
</item>
<item name="I18N" href="i18n.html"/>
+ <item name="Logger" href="logger.html"/>
+ <item name="Lifecycle" href="lifecycle/index.html"/>
+ <item name="Thread" href="thread.html"/>
</menu>
<menu name="Resources">
1.6 +3 -0 avalon-excalibur/site/xdocs/navigation.xml
Index: navigation.xml
===================================================================
RCS file: /home/cvs/avalon-excalibur/site/xdocs/navigation.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- navigation.xml 4 Apr 2004 16:26:18 -0000 1.5
+++ navigation.xml 4 Apr 2004 16:36:46 -0000 1.6
@@ -23,6 +23,9 @@
<item name="Event" href="event/index.html"/>
<item name="Fortress" href="fortress/index.html"/>
<item name="I18N" href="i18n.html"/>
+ <item name="Logger" href="logger.html"/>
+ <item name="Lifecycle" href="lifecycle/index.html"/>
+ <item name="Thread" href="thread.html"/>
</menu>
<menu name="Resources">
1.1 avalon-excalibur/site/xdocs/i18n.xml
Index: i18n.xml
===================================================================
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Documentation Team</author>
<title>Excalibur i18n</title>
</properties>
<body>
<section name="Excalibur i18n">
<subsection name="Overview">
<p>
Excalibur's Internationalization package is found in
<code>org.apache.avalon.excalibur.i18n</code>. Avalon
Excalibur includes a method of managing resources, and
an interface for specifying the resource. Support for
XML resource bundles are still under development.
</p>
</subsection>
<subsection name="Usage">
<p>
Using the i18n code is really straightforward; several
examples of internationalized applications exist within
the Avalon application family.
</p>
<p>
The following code is an example of the usage of the
i18n package.
</p>
<source>
// in a file called src/java/MyClass.java
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
public class MyClass implements MyInterface
{
private static final Resources REZ =
ResourceManager.getPackageResources( MyClass.class );
public void doStuff( Object myArg ) throws Exception
{
// ...
final String stupidArgumentIdentifier = myArg.toString();
// ...
final String message =
REZ.getString( "myclass.error.dostuff.bad-argument",
stupidArgumentIdentifier );
m_logger.error( message );
throw new SomeException( message, myArg );
}
}
# in a file called src/java/Resources.properties
myclass.error.dostuff.bad-argument=the argument passed to the \
doStuff method is invalid; it is {0}, which is plain silly!
</source>
<p>
That's basically all there is to it. If you follow this
pattern consistently, it will be extremely easy to i18n
your application by just putting in place a different
Resources.properties.
</p>
<p>
This i18n package is, indeed, a trivial wrapper around
the built-in i18n features java has using ResourceBundles
and the like. See the java api docs for
<a
href="http://java.sun.com/j2se/1.4.1/docs/api/java/util/ResourceBundle.html">ResourceBundle</a>
to learn more about i18n, and take a look at the javadoc
for Resources and ResourceManager to see which options
are available.
</p>
</subsection>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/logger.xml
Index: logger.xml
===================================================================
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Development Team</author>
<title>Excalibur Logger - Overview</title>
</properties>
<body>
<section name="Introduction" >
<p>
Find Avalon Excalibur's Log Management System in the
<code>org.apache.avalon.excalibur.logger</code> package.
Excalibur-Logger integrates neatly into the Avalon ECM
and Fortress. The main goal is to
be able to define the log categories on a component basis by
specifying a 'logger' attribute which denotes the log category
to use for a particular component (given the
component is <code>LogEnabled</code> or <code>Loggable</code>).
</p>
</section>
<section name="Not just for logkit" >
<p>
Though the documentation doesn't reflect this accurately
yet (patches welcome), excalibur-logger has been updated
to support other logging toolkits like jdk1.4 logging and
log4j as well.
</p>
</section>
<section name="Not just for ECM" >
<p>
Though the documentation doesn't reflect this accurately
yet (patches welcome), excalibur-logger is not just used
by (or usable by) ECM. Other containers can and do make
use of logger, too.
</p>
</section>
<section name="Example configurations" >
<p>
Look at this example of a component definition:
</p>
<source>
<![CDATA[
<component role="my.component.role" class="my.component.roleImpl"
logger="category.subcategory"/>
]]>
</source>
<p>
And now let's have a look at a hypothetical Excalibur-Logger configuration
using Logkit:
</p>
<source>
<![CDATA[
<?xml version="1.0"?>
<logkit>
<factories>
<factory type="file"
class="org.apache.avalon.excalibur.logger.factory.FileTargetFactory"/>
<factory type="priority-filter"
class="org.apache.avalon.excalibur.logger.factory.PriorityFilterTargetFactory"/>
</factories>
<targets>
<file id="root">
<filename>lolo/${current-dir}/lala/${foo}/logs/main.log</filename>
<format type="extended">
%7.7{priority} %5.5{time} [%8.8{category}] (%{context}): %{message}\n%{throwable}
</format>
<append>true</append>
</file>
<file id="classloader">
<filename>logs/classloader.log</filename>
<format type="raw"/>
</file>
<priority-filter id="foo" log-level="WARN">
<file>
<filename>logs/foo.log</filename>
<format type="extended">
%7.7{priority} %5.5{time}: %{message}\n%{throwable}
</format>
</file>
</priority-filter>
</targets>
<categories>
<category name="cocoon" log-level="INFO">
<log-target id-ref="root"/>
<category name="classloader" log-level="DEBUG">
<log-target id-ref="classloader"/>
</category>
</category>
<category name="foo" log-level="DEBUG">
<log-target id-ref="foo"/>
</category>
</categories>
</logkit>
]]>
</source>
<p>
As you've seen the configuration file for excalibur-logger when used
with logkit has three sections (beside the root element).
</p>
<dl>
<dt><factories></dt>
<dd>
The factories section defines the
<code>LogTargetFactory</code>s
that are used to create the needed
<code>LogTargets</code>. You'll
find the factories available in the
<code>org.apache.avalon.excalibur.logger.factory</code>
package. You can write your own factories which
only needs to implement the
<code>org.apache.avalon.excalibur.logger.LogTargetFactory</code>
interface or you extend one of the available factories
in the mentioned package.
</dd>
<dt><targets></dt>
<dd>
The targets section defines the individual
<code>LogTargets</code>.
The element name of a target definition corresponds
to a type attribute of a <factory> element. You'll
probably need to consult the javadocs of the corresponding
factory to get familiar with the configuration
options available for a particular target.
</dd>
<dt><categories></dt>
<dd>
The categories section finally assembles all together. The
name attribute of a category gives the reference used in
logger attribute in the components configuration files.
The log-level attribute gives the logging priority to the
<code>Logger</code> of that category. <category>
elements have <log-targets> children which, you
already guessed, defines the <code>LogTarget</code>s
for a particular logging category. You'll also see in the
sample above that category elements can be nested to define
sub-categories.
</dd>
</dl>
</section>
<section name="Design principles and implementation details of Excalibur-Logger">
<p>
The first abstraction is the <code>LogKitManager</code>:
</p>
<source>
public interface LogKitManager
{
Logger getLogger( String categoryName );
}
</source>
<p>
There is a implementation named <code>DefaultLogKitManager</code>
which is the only class exposed to clients. As a convenient a
additional interface is introduced for the
<code>ComponentManager</code> (stolen from the role management
system) which states that a class is willing to get a
<code>LogKitManager</code>:
</p>
<source>
public interface LogKitManageable
{
void setLogKitManager( LogKitManager logmanager );
}
</source>
<p>
This method has to be called before the configure method but after the
contextualize method.
</p>
<p>
The <code>DefaultLogKitManager</code> is <code>Configurable</code>
(as well as <code>Loggable</code> [the initial default logger] and
<code>Contextualizable</code> [to pass along for ie.
<code>ServletOutputLogTarget</code>]) and gets a
<code>Configuration</code> object as expressed in the logkit
xml syntax above. This <code>DefaultLogKitManager</code> then uses
a object of type
</p>
<source>
public interface LogTargetFactoryManager
{
LogTargetFactory getLogTargetFactory( String factoryName );
}
</source>
<p>
The <code>DefaultLogTargetFactoryManager</code> is
<code>Configurable</code> (as well as <code>Loggable</code> and
<code>Contextualizable</code>) and gets the
<code>Configuration</code> object located at the <factories>
element. It will instanciate the concrete factories into a map
keyed by the type attribute. So we are at the
<code>LogTargetFactory</code> abstraction which is:
</p>
<source>
public interface LogTargetFactory
{
LogTarget createTarget( Configuration configuration )
throws ConfigurationException;
}
</source>
<p>
It may happen that a <code>LogTargetFactory</code> needs to
create <code>LogTarget</code>s they don't know in advance
and thus an additional interface is needed:
</p>
<source>
public interface LogTargetFactoryManageable
{
void setLogTargetFactoryManager(
LogTargetFactoryManager logTargetFactoryManager );
}
</source>
<p>
This eases writing factories which acts like decorators
(<code>AsyncLogTarget</code>, <code>PriorityFilter</code>)
and thus need a LogTargetFactoryManager to create the decorated
<code>LogTargets</code> which are embeded in the configuration
of them (see <priority-filter> above).
</p>
<p>
After initializing the <code>LogTargetFactoryManager</code> a
<code>LogTargetManager</code>
</p>
<source>
public interface LogTargetManager
{
LogTarget getLogTarget( String targetId );
}
</source>
<p>
is created. The implementation <code>DefaultLogTargetManager</code>
is, you guess it, <code>Configurable</code> (as well as
<code>Loggable</code> and <code>Contextualizable</code>). The
<code>Configuration</code> object is the <targets> element
in the xml syntax and is put into a map keyed by the id
attribute of the target element. It is also
<code>LogTargetFactoryManageable</code> tob e able to create
the <code>LogTargets</code>.
</p>
<p>
The last step of the <code>DefaultLogKitManagers</code> configure
method is to create the actual categories based on the categories
elements content. It does it as the syntax will show in a
recursive way populating the Loggers retrieved by
<code>Hierarchy.getDefaultHierarchy().getLoggerFor( full_category )</code>
with the denoted <code>LogTargets</code> from the
<code>LogTargetManager</code>.
</p>
<p>
After that the <code>LogKitManager</code> is ready to be asked
for <code>Logger</code>s.
</p>
<p>
Now ECM is aware of a
"magic attributes" named logger and used like
<code>logger="category"</code> on the component definition syntax.
The classes building up ECM
are made <code>LogTargetFactoryManageable</code>. If you pass along
a <code>LogKitManager</code> to the <code>ExcaliburComponentManager</code>
it will retrieve the denoted logger
category specified with the logger attribute from the
<code>LogKitManager</code> and pass it to <code>Component</code>s
implementing <code>Loggable</code>.
</p>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/lifecycle/extension.xml
Index: extension.xml
===================================================================
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Development Team</author>
<title>Lifecycle Extensions</title>
</properties>
<body>
<section name="What are lifecycle extensions ?" >
<p>
Lifecycle extensions are additional stages a component can traverse through
during
it's lifetime. Lifecycle extensions allow a container to provide extra
functionality
to components in addition to the standard stages defined by Avalon Framework.
</p>
<p>
Avalon Framework defines a set of standard interfaces often termed as Lifecycle
stages that can be used by a container to determine the components requirements
during deployment and subsequent decommissioning.
</p>
<p>
These interfaces allows the developer to separate the various concerns involved
when
writing a component. Often termed SoC and IoC (Separation of Concerns and
Inversion of
Control), these concepts represent one of the primary advantages of using Avalon.
</p>
<p>
Sometimes it's useful to extend this development paradigm from the framework
level
into the application domain, to create customized lifecycle extensions that are
called
upon in addition to the standard set defined by the Avalon Framework.
</p>
<p>
Such custom lifecycle stages can further enable domain specific logic across
many,
perhaps even unrelated components, can reduce code duplication, and allows the
developer
to reuse the same development and thinking paradigm as the standard lifecycle
stages.
</p>
<p>
For example, you might want to pass a specialized SecurityManager to some of your
components before they are initialized, or have their internal state
persistently cached
during system shutdown and restored at during startup. You might want to pass
user
dependent decryption keys to your component, or give components the opportunity
to
recycle themselves before being disposed or returned to a pooled component
handler.
</p>
<p>
The possibilities and number of extensions are only limited by the requirements
of your
particular application domain.
</p>
<p>
This document describes how to add new lifecycle extensions using
<strong>Fortress</strong>
and <strong>Merlin</strong> containers.
This document assumes a knowledge of what an Avalon lifecycle is, and a basic
understanding
of the standard lifecycle interfaces Avalon Framework defines. References in
this document to
Service and ServiceManager can also be freely interpreted as Component and
ComponentManager
by the reader.
</p>
<note>As at the time of writing, Fortress and Merlin is the only Avalon
container that
supports lifecycle extensions, which means components that use this feature will
not work
with the other Avalon containers (ExcaliburComponentManager, Phoenix, Tweety,
etc)</note>
<p>
Support for lifecycle extensions in the other Avalon containers is technically
possible but
has not yet been discussed. Please check with the Avalon developer mailing list
if you use
one of these containers and would like to use lifecycle extensions.
</p>
</section>
<section name="How do I extend a Component's lifecycle ?" >
<p>
Extending a Component's lifecycle is straightforward. An overview of the process
follows:
</p>
<ol>
<li>Define the new component interface
<br/><br/>
Create the new interface defining the operations that should be called upon
components
that implement this interface. Using the previously mentioned examples, this
would be
your <code>SecurityManageable</code>, <code>Cacheable</code>,
<code>Decryptable</code>,
<code>Recycleable</code> interfaces.
</li>
<li>Define an extension object that calls upon the methods defined in the new
interface,
during one or more of the pre-defined phases of component's lifecycle
<br/><br/>
Create a class that implements the <code>Creator</code> and/or
<code>Accessor</code>
interfaces and implemets the interaction with target components supplied under
the
create, destroy, access and relase operations.
</li>
<li>Register your extension object
<br/><br/>
This depends on the container you are using. In
Merlin you need to include the <extensions> tag in the component .xinfo
file and
Merlin will automatically recognize it. In Fortress you register the
extension object
with a <code>LifecycleExtensionManager</code>
</li>
<li>Implement the new component interface on your component
<br/><br/>
Add the new <code>implements</code> clause to your Component, or Component
implementation,
and write any methods defined in the implemented interface.
<br/><br/>
Proceed as normal. Checking for extensions is done implicitly within both
Fortress and
Merlin. Once lifecycle extensions are registered they will be activated during
the 4
phases defined later in this document.
</li>
</ol>
</section>
<section name="When can a Component's lifecycle be extended ?" >
<p>
The life of any component can be broken down to the following phases:
</p>
<ol>
<li>Creation
<br/><br/>
When the component is instantiated.
</li>
<li>Access
<br/><br/>
When the component is accessed via a ServiceManager/Selector
(<code>lookup()/select()</code>).
</li>
<li>Release
<br/><br/>
When the component is released via a ServiceManager/Selector
(<code>release()</code>).
</li>
<li>Destruction
<br/><br/>
When the component is decommissioned, ready for garbage collection.
</li>
</ol>
<note>A component will go through it's Creation and Destruction phase only once.
Since
extension classes can implement different handling strategies (Poolable,
ThreadSafe,
etc), the access and release phases of a component can be applied multiple
times.</note>
<p>
Lifecycle extensions can be added to any of the above defined phases. This allows
you to control the interception point your particular extension will be applied
under.
</p>
<p>
For example, thread or user dependent extensions would be added at the access
and release
levels (ie. when the component is retrieved and returned to the ServiceManager)
as they
depend on runtime data not available until they are actually used.
</p>
<p>
More static, or global extensions would be added at the creation or destruction
level, since
they do not depend on any external data that change during runtime, nor are they
particular
to any one context of use.
</p>
</section>
<section name="Lifestyle Extension Interfaces" >
<p>
A container manages extensions using an extension handler. Handlers may
implement
the <code>Creator</code> and/or <code>Accessor</code> interfaces. A creator
extension
will be activated during the create and destroy stages of a component
lifecycle. A
accessor extension will be activated during the access and release stages.
</p>
<section name="The Creator Interface" >
<p>The <code>Creator</code> interface describes the create and destroy
stages that occur between a component and a container
during service management. Lifecycle extensions supporting create
and destroy stages must implement this interface.</p>
<source>
package org.apache.avalon.lifecycle;
import org.apache.avalon.framework.context.Context;
public interface Creator
{
/**
* Create stage handler.
*
* @param object the object that is being created
* @param context the context instance required by the create handler
* implementation
* @exception Exception if an error occurs
*/
void create( Object object, Context context )
throws Exception;
/**
* Destroy stage handler.
*
* @param object the object that is being destroyed
* @param context the context instance required by the handler
* implementation
*/
void destroy( Object object, Context context );
}
</source>
</section>
<section name="Accessor Interface" >
<p>
The <code>Accessor</code> interface describes the access and release
stages that occur between a service or component manager and a container
during service deployment. Lifecycle extensions supporting access
and release stages must implement this interface.
</p>
<source>
package org.apache.avalon.lifecycle;
import org.apache.avalon.framework.context.Context;
public interface Accessor
{
/**
* Access stage handler.
*
* @param object the object that is being accessed
* @param context the context instance required by the access handler
* implementation
* @exception Exception if an error occurs
*/
void access( Object object, Context context )
throws Exception;
/**
* Release stage handler.
*
* @param object the object that is being released
* @param context the context instance required by the release handler
* implementation
*/
void release( Object object, Context context );
}
</source>
</section>
</section>
<section name="Need more information ?" >
<p>
If you have any particular questions, comments, etc, please send an email to the
Avalon
developer mailing <a href="mailto:[EMAIL PROTECTED]">list</a>.
</p>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/lifecycle/fortress.xml
Index: fortress.xml
===================================================================
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Development Team</author>
<title>Fortress Lifecycle Extensions</title>
</properties>
<body>
<section name="Example" >
<p>
Let's look at a simple example. The following is also available as a working
sample
in Fortress' examples directory.
</p>
<p>
Our example implements a Lifecycle extension for passing a
<code>SecurityManager</code> to
Components. We'll call it the <code>SecurityManageable</code> interface.
</p>
<section name="Define the component extension interface" >
<p>
First we define the new Component extension interface.
</p>
<source>
/**
* Simple custom lifecycle extension interface for supplying a component
* with a security manager.
*/
public interface SecurityManageable
{
/**
* Pass a SecurityManager object to the component
*
* @param manager a SecurityManager value
*/
void secure( SecurityManager manager )
throws SecurityException;
}
</source>
</section>
<section name="Create the lifecycle extensions class" >
<p>
Next we define the actual extension implementation which invokes the
<code>secure()</code>
method. We extend from <code>AbstractAccessor</code> since we only want
<code>secure()</code> to be invoked upon each access (ie. lookup()) to the
component, and
don't need to implement the other 3 LifecycleExtension methods (create, release,
and
destroy).
</p>
<source>
/**
* Some custom extensions for this container's components.
*/
public class Extensions
extends AbstractAccessor
{
/**
* Access, called when the given component is being
* accessed (ie. via lookup() or select()).
*
* @param component a Component instance
* @param context a Context instance
* @exception Exception if an error occurs
*/
public void access( Object component, Context context )
throws Exception
{
if ( component instanceof SecurityManageable )
{
// pass in a simple security manager, a real system might want to pass
// in specialized/custom security managers
( ( SecurityManageable ) component ).secure( new SecurityManager() );
}
}
}
</source>
<note>An extension class may run components through any given number of
extensions, and are not limited to just one.</note>
</section>
<section name="Register the lifecycle extensions class" >
<p>
We then inform our container about the extension. This could be done in several
different
ways, for simplicity we'll extend <code>initialize()</code> and add it to the
<code>LifecycleExtensionManager</code> there.
</p>
<p>
(an alternative might be to initialize a LifecycleExtensionManager before
creating the
container and pass it in via the
<code>FortressConfig.setExtensionManager()</code> method,
or to create a LifecycleExtensionManager subclass that includes the extension
preset)
</p>
<source>
/**
* Simple container that includes custom lifecycle extensions.
*/
public final class ExtendedContainer
extends DefaultContainer
{
public void initialize()
throws Exception
{
super.initialize();
m_extManager.addExtension( new Extensions() );
}
}
</source>
</section>
<section name="Use the new component interface" >
<p>
To use the new SecurityManageable lifecycle extension, we simply implement
SecurityManageable just as we do with any other Avalon lifecycle interfaces
(assuming a predefined Component interface <code>ExtendedComponent</code>).
</p>
<source>
/**
* ExtendedComponentImpl, demonstrating the use of a custom
* lifecycle stage SecurityManageable. This code does
* a simple access check for several files on the file system and logs
* the results accordingly.
*/
public class ExtendedComponentImpl
extends AbstractLogEnabled
implements ExtendedComponent, SecurityManageable
{
/**
* Pass a SecurityManager object to the component
*
* @param manager a SecurityManager value
*/
public void secure( final SecurityManager manager )
throws SecurityException
{
getLogger().info( "Received SecurityManager instance: " + manager );
final String[] files = { "/tmp", "/vmlinuz", "/usr/lib/libc.a" };
for ( int i = 0; i < files.length; ++i )
{
try
{
manager.checkRead( files[ i ] );
getLogger().info( "Thread can read " + files[ i ] );
}
catch ( SecurityException e )
{
getLogger().info( "Thread can not read " + files[ i ] );
}
}
}
}
</source>
</section>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/lifecycle/index.xml
Index: index.xml
===================================================================
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Development Team</author>
<title>Lifecycle Extensions</title>
</properties>
<body>
<section name="Introduction" >
<p>
The Lifecycle package contains a set of interfaces and classes
supporting portable lifecycle extensions.
</p>
<p>
Contributions to this project are based on co-development actives by
container projects aiming towards cross-container component portability
and consistent service management.
</p>
<p>
The first step in the container project has been undertaken between the
Fortress and Merlin containers on the subject of lifestyle extension
support. The original design and implementation of lifecycle extensions
by Marcus Crafter was implemented using the Fortress container.
Subsequently, and alternative implementation based on Marcus' design was
introduced using the Merlin container leading to two incompatible
solutions aiming at the same objective. Through a process of
cross-project collaboration, the Fortress and Merlin developers reached
consensus on a common set of APIs and abstract implementation. These
resources constitute the first sub-project of the Excalibur Container
package.
</p>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/lifecycle/interfaces.xml
Index: interfaces.xml
===================================================================
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Development Team</author>
<title>Extension Interfaces</title>
</properties>
<body>
<section name="Lifestyle Extension Interfaces" >
<p>
A container manages extensions using an extension handler. Handlers
may implement the <code>Creator</code> and/or <code>Accessor</code>
interfaces. A creator extension will be activated during the create and
destroy stages of a component lifecycle. A accessor extension will be
activated during the access and release stages.
</p>
<section name="The Creator Interface" >
<p>
The <code>Creator</code> interface describes the create and destroy
stages that occur between a component and a container
during service management. Lifecycle extensions supporting create
and destroy stages must implement this interface.
</p>
<source>
package org.apache.avalon.lifecycle;
import org.apache.avalon.framework.context.Context;
public interface Creator
{
/**
* Create stage handler.
*
* @param object the object that is being created
* @param context the context instance required by the create handler
* implementation
* @exception Exception if an error occurs
*/
void create( Object object, Context context )
throws Exception;
/**
* Destroy stage handler.
*
* @param object the object that is being destroyed
* @param context the context instance required by the handler
* implementation
*/
void destroy( Object object, Context context );
}
</source>
</section>
<section name="Accessor Interface" >
<p>
The <code>Accessor</code> interface describes the access and release
stages that occur between a service or component manager and a
container during service deployment. Lifecycle extensions supporting
access and release stages must implement this interface.
</p>
<source>
package org.apache.avalon.lifecycle;
import org.apache.avalon.framework.context.Context;
public interface Accessor
{
/**
* Access stage handler.
*
* @param object the object that is being accessed
* @param context the context instance required by the access handler
* implementation
* @exception Exception if an error occurs
*/
void access( Object object, Context context )
throws Exception;
/**
* Release stage handler.
*
* @param object the object that is being released
* @param context the context instance required by the release handler
* implementation
*/
void release( Object object, Context context );
}
</source>
</section>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/lifecycle/merlin.xml
Index: merlin.xml
===================================================================
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<author email="[EMAIL PROTECTED]">Avalon Development Team</author>
<title>Lifecycle Extensions</title>
</properties>
<body>
<section name="Example" >
<section name="Create your lifestyle stage interface" >
<p>
The following interface is your domain specific lifecycle stage
interface. It is the interface that an extension handler will use to
interact with your component during deployment and decommissioning.
</p>
<source>
public interface Exploitable
{
/**
* Operation invoked by an exploitation manager.
* @param message a message to be displayed
*/
void exploit( String message );
}
</source>
</section>
<section name="Create the lifestyle extension handler" >
<p>
An extension handler is the implementation class that will be
activated by the Merlin container to handle domain specific tasks
during the deployment and decommissioning phases. The extension can
implement etier or both of the Creator and Accessor interfaces
depeding on the particular extension requirements. IN this example we
are defining a simple creation stage handler that supplies a message
to an instance of Exploitable.
</p>
<source>
public class ExploitationManager implements Creator
{
/**
* Operation invoked by a container to request creation
* stage extension interception.
* @param object a component to manager
* @param context the context
*/
public void create( Object object, Context context )
{
if( object instanceof Exploitable )
{
((Expoitable)object).exploit( "hello" );
}
}
/**
* Operation invoked by a container to request destroy
* stage extension interception.
* @param object a component to manager
* @param context the context
*/
public void destroy( Object object, Context context )
{
}
}
</source>
<p>
To complete the defintion of you extension handler you need to prepare
the meta-info that will be used by Merlin to identify the extension
and the stage interface is supports. The following <type/>
declaration includes an <extensions/> tag that contains a
<reference/> element that includes the reference to the
Exploitable lifecycle stage interface. This is the key that Merlin
uses to associate a handler with a component. If you extension class
requires any specific context values, they should be declared in a
context element within the extension element.
</p>
<source>
<type>
<info>
<name>my-extension-handler</name>
</info>
<extensions>
<extension>
<name>exploitation</name>
<reference type="Exploitable" version="1.0"/>
</extension>
</extensions>
</type>
</source>
</section>
<section name="Create a component implementing the stage interface" >
<source>
public class MyComponent extends AbstractLogEnabled implements Exploitable
{
/**
* Operation invoked by an exploitation manager.
* @param message a message to be displayed
*/
public void exploit( String message )
{
getLogger().info( message );
}
}
</source>
<p>
To complete the defintion of your component you need to prepare the
meta-info that will be used by Merlin to identify the stage interface
is requires a handler for. The following <type/> declaration
includes an <stage/> tag that contains a <reference/>
element that includes the reference to the Exploitable lifecycle stage
interface. This is the key that Merlin uses to associate the component
with a handler capable of handling the Exploitable interface.
</p>
<source>
<type>
<info>
<name>my-component</name>
</info>
<stages>
<stage>
<name>exploit-me</name>
<reference type="Exploitable" version="1.0"/>
</stage>
</stages>
</type>
</source>
</section>
<section name="Register you component and the extension" >
<p>
To complete the process you need to declare your handler and component
in a jar manifest file. The following entries show the declaration of
the component and the extension handler.
</p>
<source>
Manifest-Version: 1.0
Created-By: Ant 1.5
Name: MyComponent.class
Avalon: Type
Name: ExploitationManager.class
Avalon: Type
</source>
</section>
<section name="Execute the example" >
<p>
To execute the example you simply need to include a reference to you
component within a Merlin container declaration. The following XML
source declares a Merlin kernel, container, and component. You don't
need to include the handler because Merlin can sort that out itself
based on the information supplied in the meta-info declarations.
</p>
<source>
<kernel>
<container name="my-container>
<classpath>
<fileset dir="lib">
<include name="my-domo.jar"/>
</fileset>
</classpath>
<component name="demo" class="MyComponent" activation="startup"/>
<container>
</kernel>
</source>
</section>
</section>
</body>
</document>
1.1 avalon-excalibur/site/xdocs/lifecycle/navigation.xml
Index: navigation.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<project>
<title>Avalon Sandbox</title>
<body>
<links>
<item name="Apache" href="http://apache.org/"/>
<item name="Avalon" href="http://avalon.apache.org/"/>
<item name="Framework" href="http://avalon.apache.org/product/framework/"/>
<item name="Merlin" href="http://avalon.apache.org/product/containers/"/>
<item name="Planet" href="http://avalon.apache.org/product/components/"/>
</links>
<menu name="About Excalibur">
<item name="Overview" href="/index.html"/>
<item name="Configuration" href="configuration.html"/>
<item name="I18N" href="i18n/index.html"/>
<item name="Sourceresolver" href="sourceresolve-index.html"/>
<item name="Store" href="store-index.html"/>
<item name="ECM" href="component.html"/>
<item name="Event" href="event/index.html"/>
<item name="Fortress" href="fortress/index.html"/>
<item name="I18N" href="i18n.html"/>
<item name="Logger" href="logger.html"/>
<item name="Lifecycle" href="lifecycle/index.html">
<item name="Overview" href="lifecycle/index.html"/>
<item name="Extensions" href="lifecycle/extension.html"/>
<item name="Interfaces" href="lifecycle/interfaces.html"/>
<item name="Tutorial" href="lifecycle/fortress.html"/>
</item>
<item name="Thread" href="thread.html"/>
</menu>
<menu name="Resources">
<item name="Javadocs" href="http://avalon.apache.org/excalibur/api/"/>
<item name="Download" href="http://avalon.apache.org/download.cgi"/>
<item name="Where's my documentation???" href="/no-docs-available.html"/>
</menu>
</body>
</project>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]