2010/12/15 - Apache Excalibur has been retired.

For more information, please explore the Attic.

Example

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.

Define the component extension 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;
   }
                

Create the lifecycle extensions class

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() );
           }
       }
   }
                
An extension class may run components through any given number of extensions, and are not limited to just one.

Register the lifecycle extensions class

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() );
       }
   }
                

Use the new component interface

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 ] );
               }
           }
       }
   }