blob: 654ec049ebc210078c38a1f454abc6d2e819cf6f [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.embeddor;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Map;
import org.apache.avalon.excalibur.io.ExtensionFileFilter;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.myrmidon.api.JavaVersion;
import org.apache.myrmidon.components.aspect.AspectManager;
import org.apache.myrmidon.components.builder.ProjectBuilder;
import org.apache.myrmidon.components.configurer.Configurer;
import org.apache.myrmidon.components.converter.ConverterRegistry;
import org.apache.myrmidon.components.converter.MasterConverter;
import org.apache.myrmidon.components.deployer.Deployer;
import org.apache.myrmidon.components.deployer.DeploymentException;
import org.apache.myrmidon.components.executor.Executor;
import org.apache.myrmidon.components.workspace.Workspace;
import org.apache.myrmidon.components.model.Project;
import org.apache.myrmidon.components.role.RoleManager;
import org.apache.myrmidon.components.type.TypeFactory;
import org.apache.myrmidon.components.type.TypeManager;
/**
* Default implementation of Embeddor.
* Instantiate this to embed inside other applications.
*
* @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
*/
public class DefaultEmbeddor
extends AbstractLoggable
implements Embeddor
{
private Deployer m_deployer;
private RoleManager m_roleManager;
private AspectManager m_aspectManager;
private TypeManager m_typeManager;
private MasterConverter m_converter;
private ConverterRegistry m_converterRegistry;
private Executor m_executor;
private Configurer m_configurer;
private DefaultComponentManager m_componentManager;
private Parameters m_parameters;
private Parameters m_defaults;
private File m_homeDir;
private File m_binDir;
private File m_libDir;
private File m_taskLibDir;
/**
* Setup basic properties of engine.
* Called before init() and can be used to specify alternate components in system.
*
* @param properties the properties
*/
public void parameterize( final Parameters parameters )
{
m_parameters = parameters;
}
public Project createProject( final String location,
String type,
final Parameters parameters )
throws Exception
{
if( null == type )
{
type = guessTypeFor( location );
}
final ProjectBuilder builder = getProjectBuilder( type, parameters );
return builder.build( location );
}
private String guessTypeFor( final String location )
{
return FileUtil.getExtension( location );
}
private ProjectBuilder getProjectBuilder( final String type,
final Parameters parameters )
throws Exception
{
final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.ROLE );
final ProjectBuilder builder = (ProjectBuilder)factory.create( type );
setupLogger( builder );
if( builder instanceof Composable )
{
((Composable)builder).compose( m_componentManager );
}
if( builder instanceof Parameterizable )
{
((Parameterizable)builder).parameterize( parameters );
}
if( builder instanceof Initializable )
{
((Initializable)builder).initialize();
}
return builder;
}
public Workspace createWorkspace( final Parameters parameters )
throws Exception
{
final String component = getParameter( Workspace.ROLE );
final Workspace workspace =
(Workspace)createComponent( component, Workspace.class );
setupLogger( workspace );
if( workspace instanceof Composable )
{
((Composable)workspace).compose( m_componentManager );
}
if( workspace instanceof Parameterizable )
{
((Parameterizable)workspace).parameterize( parameters );
}
if( workspace instanceof Initializable )
{
((Initializable)workspace).initialize();
}
return workspace;
}
/**
* Initialize the system.
*
* @exception Exception if an error occurs
*/
public void initialize()
throws Exception
{
//setup default properties
m_defaults = createDefaultParameters();
//create all the components
createComponents();
//setup the component manager
m_componentManager = createComponentManager();
setupComponents();
setupFiles();
}
public void start()
throws Exception
{
final ExtensionFileFilter filter = new ExtensionFileFilter( ".atl" );
deployFromDirectory( m_deployer, m_taskLibDir, filter );
}
public void stop()
{
//Undeploy all the tasks by killing ExecutionFrame???
}
/**
* Dispose engine.
*
* @exception Exception if an error occurs
*/
public void dispose()
{
m_aspectManager = null;
m_roleManager = null;
m_converterRegistry = null;
m_converter = null;
m_executor = null;
m_deployer = null;
m_configurer = null;
m_componentManager = null;
m_parameters = null;
m_defaults = null;
m_homeDir = null;
m_binDir = null;
m_libDir = null;
m_taskLibDir = null;
}
/**
* Create default properties which includes default names of all components.
* Overide this in sub-classes to change values.
*
* @return the Parameters
*/
private Parameters createDefaultParameters()
{
final Parameters defaults = new Parameters();
//create all the default properties for files/directories
defaults.setParameter( "myrmidon.bin.path", "bin" );
defaults.setParameter( "myrmidon.lib.path", "lib" );
//create all the default properties for components
defaults.setParameter( AspectManager.ROLE,
"org.apache.myrmidon.components.aspect.DefaultAspectManager" );
defaults.setParameter( RoleManager.ROLE,
"org.apache.myrmidon.components.role.DefaultRoleManager" );
defaults.setParameter( MasterConverter.ROLE,
"org.apache.myrmidon.components.converter.DefaultMasterConverter" );
defaults.setParameter( ConverterRegistry.ROLE,
"org.apache.myrmidon.components.converter.DefaultConverterRegistry" );
defaults.setParameter( TypeManager.ROLE,
"org.apache.myrmidon.components.type.DefaultTypeManager" );
defaults.setParameter( Executor.ROLE,
//"org.apache.myrmidon.components.executor.DefaultExecutor" );
//"org.apache.myrmidon.components.executor.PrintingExecutor" );
"org.apache.myrmidon.components.executor.AspectAwareExecutor" );
defaults.setParameter( Workspace.ROLE,
"org.apache.myrmidon.components.workspace.DefaultWorkspace" );
defaults.setParameter( Deployer.ROLE,
"org.apache.myrmidon.components.deployer.DefaultDeployer" );
defaults.setParameter( Configurer.ROLE,
"org.apache.myrmidon.components.configurer.DefaultConfigurer" );
return defaults;
}
/**
* Create a ComponentManager containing all components in engine.
*
* @return the ComponentManager
*/
private DefaultComponentManager createComponentManager()
{
final DefaultComponentManager componentManager = new DefaultComponentManager();
componentManager.put( MasterConverter.ROLE, m_converter );
//Following components required when Myrmidon is used as build tool
componentManager.put( Embeddor.ROLE, this );
//Following components required when Myrmidon allows user deployment of tasks etal.
componentManager.put( RoleManager.ROLE, m_roleManager );
componentManager.put( Deployer.ROLE, m_deployer );
//Following components used when want to types (ie tasks/mappers etc)
componentManager.put( TypeManager.ROLE, m_typeManager );
componentManager.put( ConverterRegistry.ROLE, m_converterRegistry );
componentManager.put( AspectManager.ROLE, m_aspectManager );
//Following components required when allowing Container tasks
componentManager.put( Configurer.ROLE, m_configurer );
componentManager.put( Executor.ROLE, m_executor );
return componentManager;
}
/**
* Create all required components.
*
* @exception Exception if an error occurs
*/
private void createComponents()
throws Exception
{
String component = null;
component = getParameter( ConverterRegistry.ROLE );
m_converterRegistry = (ConverterRegistry)createComponent( component, ConverterRegistry.class );
component = getParameter( MasterConverter.ROLE );
m_converter = (MasterConverter)createComponent( component, MasterConverter.class );
component = getParameter( Configurer.ROLE );
m_configurer = (Configurer)createComponent( component, Configurer.class );
component = getParameter( TypeManager.ROLE );
m_typeManager = (TypeManager)createComponent( component, TypeManager.class );
component = getParameter( RoleManager.ROLE );
m_roleManager = (RoleManager)createComponent( component, RoleManager.class );
component = getParameter( AspectManager.ROLE );
m_aspectManager = (AspectManager)createComponent( component, AspectManager.class );
component = getParameter( Deployer.ROLE );
m_deployer = (Deployer)createComponent( component, Deployer.class );
component = getParameter( Executor.ROLE );
m_executor = (Executor)createComponent( component, Executor.class );
}
/**
* Setup all the components. (ir run all required lifecycle methods).
*
* @exception Exception if an error occurs
*/
private void setupComponents()
throws Exception
{
setupComponent( m_roleManager );
setupComponent( m_aspectManager );
setupComponent( m_converterRegistry );
setupComponent( m_converter );
setupComponent( m_executor );
setupComponent( m_deployer );
setupComponent( m_configurer );
}
/**
* Setup an individual component.
*
* @param component the component
* @exception Exception if an error occurs
*/
private void setupComponent( final Component component )
throws Exception
{
setupLogger( component );
if( component instanceof Composable )
{
((Composable)component).compose( m_componentManager );
}
if( component instanceof Initializable )
{
((Initializable)component).initialize();
}
}
/**
* Setup all the files attributes.
*/
private void setupFiles()
throws Exception
{
String filepath = null;
filepath = getParameter( "myrmidon.home" );
m_homeDir = (new File( filepath )).getAbsoluteFile();
checkDirectory( m_homeDir, "home" );
filepath = getParameter( "myrmidon.bin.path" );
m_binDir = resolveDirectory( filepath, "bin-dir" );
filepath = getParameter( "myrmidon.lib.path" );
m_taskLibDir = resolveDirectory( filepath, "task-lib-dir" );
}
/**
* Retrieve value of named property.
* First access passed in properties and then the default properties.
*
* @param name the name of property
* @return the value of property or null
*/
private String getParameter( final String name )
{
String value = m_parameters.getParameter( name, null );
if( null == value )
{
value = m_defaults.getParameter( name, null );
}
return value;
}
/**
* Resolve a directory relative to another base directory.
*
* @param dir the base directory
* @param name the relative directory
* @return the created File
* @exception Exception if an error occurs
*/
private File resolveDirectory( final String dir, final String name )
throws Exception
{
final File file = FileUtil.resolveFile( m_homeDir, dir );
checkDirectory( file, name );
return file;
}
/**
* Verify file is a directory else throw an exception.
*
* @param file the File
* @param name the name of file type (used in error messages)
*/
private void checkDirectory( final File file, final String name )
throws Exception
{
if( !file.exists() )
{
throw new Exception( name + " (" + file + ") does not exist" );
}
else if( !file.isDirectory() )
{
throw new Exception( name + " (" + file + ") is not a directory" );
}
}
/**
* Helper method to retrieve current JVM version.
*
* @return the current JVM version
*/
private JavaVersion getJavaVersion()
{
JavaVersion version = JavaVersion.JAVA1_0;
try
{
Class.forName( "java.lang.Void" );
version = JavaVersion.JAVA1_1;
Class.forName( "java.lang.ThreadLocal" );
version = JavaVersion.JAVA1_2;
Class.forName( "java.lang.StrictMath" );
version = JavaVersion.JAVA1_3;
}
catch( final ClassNotFoundException cnfe ) {}
return version;
}
/**
* Create a component that implements an interface.
*
* @param component the name of the component
* @param clazz the name of interface/type
* @return the created object
* @exception Exception if an error occurs
*/
private Object createComponent( final String component, final Class clazz )
throws Exception
{
try
{
final Object object = Class.forName( component ).newInstance();
if( !clazz.isInstance( object ) )
{
throw new Exception( "Object " + component + " is not an instance of " +
clazz );
}
return object;
}
catch( final IllegalAccessException iae )
{
throw new Exception( "Non-public constructor for " + clazz + " " + component );
}
catch( final InstantiationException ie )
{
throw new Exception( "Error instantiating class for " + clazz + " " + component );
}
catch( final ClassNotFoundException cnfe )
{
throw new Exception( "Could not find the class for " + clazz +
" (" + component + ")" );
}
}
private void deployFromDirectory( final Deployer deployer,
final File directory,
final FilenameFilter filter )
throws DeploymentException
{
final File[] files = directory.listFiles( filter );
if( null != files )
{
deployFiles( deployer, files );
}
}
private void deployFiles( final Deployer deployer, final File[] files )
throws DeploymentException
{
for( int i = 0; i < files.length; i++ )
{
final String filename = files[ i ].getName();
int index = filename.lastIndexOf( '.' );
if( -1 == index ) index = filename.length();
final String name = filename.substring( 0, index );
try
{
final File file = files[ i ].getCanonicalFile();
deployer.deploy( file );
}
catch( final DeploymentException de )
{
throw de;
}
catch( final Exception e )
{
throw new DeploymentException( "Unable to retrieve filename for file " +
files[ i ], e );
}
}
}
}