| /* |
| * 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 ); |
| } |
| } |
| } |
| } |