blob: 965dde3dcb7adaa1a0126103dbc3b3d7a8a0216f [file] [log] [blame]
/*
* 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 file.
*/
package org.apache.myrmidon.components.executor;
import java.util.HashMap;
import java.util.ArrayList;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.log.Logger;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.aspects.AspectHandler;
import org.apache.myrmidon.components.aspect.AspectManager;
public class AspectAwareExecutor
extends DefaultExecutor
{
private final static Parameters EMPTY_PARAMETERS;
private final static Configuration[] EMPTY_ELEMENTS = new Configuration[ 0 ];
static
{
EMPTY_PARAMETERS = new Parameters();
EMPTY_PARAMETERS.makeReadOnly();
}
private AspectManager m_aspectManager;
/**
* Retrieve relevent services.
*
* @param componentManager the ComponentManager
* @exception ComponentException if an error occurs
*/
public void compose( final ComponentManager componentManager )
throws ComponentException
{
super.compose( componentManager );
m_aspectManager = (AspectManager)componentManager.lookup( AspectManager.ROLE );
}
public void execute( final Configuration taskModel, final ExecutionFrame frame )
throws TaskException
{
try
{
executeTask( taskModel, frame );
}
catch( final TaskException te )
{
if( false == getAspectManager().error( te ) )
{
throw te;
}
}
}
private void executeTask( Configuration taskModel, final ExecutionFrame frame )
throws TaskException
{
taskModel = getAspectManager().preCreate( taskModel );
taskModel = prepareAspects( taskModel );
getLogger().debug( "Pre-Create" );
final Task task = createTask( taskModel.getName(), frame );
getAspectManager().postCreate( task );
getLogger().debug( "Pre-Loggable" );
final Logger logger = frame.getLogger();
getAspectManager().preLoggable( logger );
doLoggable( task, taskModel, logger );
getLogger().debug( "Contextualizing" );
doContextualize( task, taskModel, frame.getContext() );
getLogger().debug( "Composing" );
doCompose( task, taskModel, frame.getComponentManager() );
getLogger().debug( "Configuring" );
getAspectManager().preConfigure( taskModel );
doConfigure( task, taskModel, frame.getContext() );
getLogger().debug( "Initializing" );
doInitialize( task, taskModel );
getLogger().debug( "Executing" );
getAspectManager().preExecute();
doExecute( taskModel, task );
getLogger().debug( "Disposing" );
getAspectManager().preDestroy();
doDispose( task, taskModel );
}
protected void doExecute( final Configuration taskModel, final Task task )
throws TaskException
{
task.execute();
}
//TODO: Extract and clean taskModel here.
//Get all parameters from model and provide to appropriate aspect.
//aspect( final Parameters parameters, final Configuration[] elements )
private final Configuration prepareAspects( final Configuration taskModel )
throws TaskException
{
final DefaultConfiguration newTaskModel =
new DefaultConfiguration( taskModel.getName(), taskModel.getLocation() );
final HashMap parameterMap = new HashMap();
final HashMap elementMap = new HashMap();
processAttributes( taskModel, newTaskModel, parameterMap );
processElements( taskModel, newTaskModel, elementMap );
dispatchAspectsSettings( parameterMap, elementMap );
checkForUnusedSettings( parameterMap, elementMap );
return newTaskModel;
}
private final void dispatchAspectsSettings( final HashMap parameterMap,
final HashMap elementMap )
throws TaskException
{
final String[] names = getAspectManager().getNames();
for( int i = 0; i < names.length; i++ )
{
final ArrayList elementList = (ArrayList)elementMap.remove( names[ i ] );
Parameters parameters = (Parameters)parameterMap.remove( names[ i ] );
if( null == parameters ) parameters = EMPTY_PARAMETERS;
Configuration[] elements = null;
if( null == elementList ) elements = EMPTY_ELEMENTS;
else
{
elements = (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
}
dispatch( names[ i ], parameters, elements );
}
}
private final void checkForUnusedSettings( final HashMap parameterMap,
final HashMap elementMap )
throws TaskException
{
if( 0 != parameterMap.size() )
{
final String[] namespaces =
(String[])parameterMap.keySet().toArray( new String[ 0 ] );
for( int i = 0; i < namespaces.length; i++ )
{
final String namespace = namespaces[ i ];
final Parameters parameters = (Parameters)parameterMap.get( namespace );
final ArrayList elementList = (ArrayList)elementMap.remove( namespace );
Configuration[] elements = null;
if( null == elementList ) elements = EMPTY_ELEMENTS;
else
{
elements = (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
}
unusedSetting( namespace, parameters, elements );
}
}
if( 0 != elementMap.size() )
{
final String[] namespaces =
(String[])elementMap.keySet().toArray( new String[ 0 ] );
for( int i = 0; i < namespaces.length; i++ )
{
final String namespace = namespaces[ i ];
final ArrayList elementList = (ArrayList)elementMap.remove( namespace );
final Configuration[] elements =
(Configuration[])elementList.toArray( EMPTY_ELEMENTS );
unusedSetting( namespace, EMPTY_PARAMETERS, elements );
}
}
}
private void unusedSetting( final String namespace,
final Parameters parameters,
final Configuration[] elements )
throws TaskException
{
throw new TaskException( "Unused aspect settings for namespace " + namespace +
" (parameterCount=" + parameters.getNames().length +
" elementCount=" + elements.length + ")" );
}
private void dispatch( final String namespace,
final Parameters parameters,
final Configuration[] elements )
throws TaskException
{
getAspectManager().dispatchAspectSettings( namespace, parameters, elements );
if( getLogger().isDebugEnabled() )
{
getLogger().debug( "Dispatching Aspect Settings to: " + namespace +
" parameterCount=" + parameters.getNames().length +
" elementCount=" + elements.length );
}
}
private final void processElements( final Configuration taskModel,
final DefaultConfiguration newTaskModel,
final HashMap map )
{
final Configuration[] elements = taskModel.getChildren();
for( int i = 0; i < elements.length; i++ )
{
final String name = elements[ i ].getName();
final int index = name.indexOf( ':' );
if( -1 == index )
{
newTaskModel.addChild( elements[ i ] );
}
else
{
final String namespace = name.substring( 0, index );
final String localName = name.substring( index + 1 );
final ArrayList elementSet = getElements( namespace, map );
elementSet.add( elements[ i ] );
}
}
}
private final void processAttributes( final Configuration taskModel,
final DefaultConfiguration newTaskModel,
final HashMap map )
{
final String[] attributes = taskModel.getAttributeNames();
for( int i = 0; i < attributes.length; i++ )
{
final String name = attributes[ i ];
final String value = taskModel.getAttribute( name, null );
final int index = name.indexOf( ':' );
if( -1 == index )
{
newTaskModel.setAttribute( name, value );
}
else
{
final String namespace = name.substring( 0, index );
final String localName = name.substring( index + 1 );
final Parameters parameters = getParameters( namespace, map );
parameters.setParameter( localName, value );
}
}
}
private final ArrayList getElements( final String namespace, final HashMap map )
{
ArrayList elements = (ArrayList)map.get( namespace );
if( null == elements )
{
elements = new ArrayList();
map.put( namespace, elements );
}
return elements;
}
private final Parameters getParameters( final String namespace, final HashMap map )
{
Parameters parameters = (Parameters)map.get( namespace );
if( null == parameters )
{
parameters = new Parameters();
map.put( namespace, parameters );
}
return parameters;
}
protected final AspectManager getAspectManager()
{
return m_aspectManager;
}
}