Let's look at a simple example. The following is also available as a working sample in Fortress' examples directory.
Our example implements a Lifecycle extension for passing a
SecurityManager
to
Components. We'll call it the
SecurityManageable
interface.
First we define the new Component extension interface.
/** * 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; }
Next we define the actual extension implementation which invokes the
secure()
method. We extend from
AbstractAccessor
since we only want
secure()
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).
/** * 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() ); } } }
We then inform our container about the extension. This could be done in several different
ways, for simplicity we'll extend
initialize()
and add it to the
LifecycleExtensionManager
there.
(an alternative might be to initialize a LifecycleExtensionManager before creating the
container and pass it in via the
FortressConfig.setExtensionManager()
method,
or to create a LifecycleExtensionManager subclass that includes the extension preset)
/** * 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() ); } }
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
ExtendedComponent
).
/** * 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 ] ); } } } }