blob: c92de1575cecaf7974b873184f69133bfd2861dc [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.deployer;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashMap;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.components.converter.ConverterRegistry;
import org.apache.myrmidon.components.type.DefaultTypeFactory;
import org.apache.myrmidon.components.type.TypeManager;
import org.apache.myrmidon.components.role.RoleManager;
import org.apache.myrmidon.converter.Converter;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* This class deploys a .tsk file into a registry.
*
* @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
*/
public class DefaultDeployer
extends AbstractLoggable
implements Deployer, Initializable, Composable
{
private final static String TYPE_DESCRIPTOR = "META-INF/ant-types.xml";
private ConverterRegistry m_converterRegistry;
private TypeManager m_typeManager;
private RoleManager m_roleManager;
/**
* Retrieve relevent services needed to deploy.
*
* @param componentManager the ComponentManager
* @exception ComponentException if an error occurs
*/
public void compose( final ComponentManager componentManager )
throws ComponentException
{
m_converterRegistry = (ConverterRegistry)componentManager.lookup( ConverterRegistry.ROLE );
m_typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE );
m_roleManager = (RoleManager)componentManager.lookup( RoleManager.ROLE );
}
public void initialize()
throws Exception
{
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
final SAXParser saxParser = saxParserFactory.newSAXParser();
final XMLReader parser = saxParser.getXMLReader();
//parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false );
final SAXConfigurationHandler handler = new SAXConfigurationHandler();
parser.setContentHandler( handler );
parser.setErrorHandler( handler );
final ClassLoader classLoader = getClass().getClassLoader();
final DefaultTypeFactory factory = new DefaultTypeFactory( classLoader );
final Enumeration enum = classLoader.getResources( Deployment.DESCRIPTOR_NAME );
while( enum.hasMoreElements() )
{
final URL url = (URL)enum.nextElement();
parser.parse( url.toString() );
getLogger().debug( "deploying " + url );
deployFromDescriptor( handler.getConfiguration(), classLoader, url );
}
}
public void deploy( final File file )
throws DeploymentException
{
getLogger().info( "Deploying AntLib file (" + file + ")" );
checkFile( file );
final Deployment deployment = new Deployment( file );
final Configuration descriptor = deployment.getDescriptor();
final URL[] urls = new URL[] { deployment.getURL() };
final URLClassLoader classLoader =
new URLClassLoader( urls, Thread.currentThread().getContextClassLoader() );
try
{
deployFromDescriptor( descriptor, classLoader, deployment.getURL() );
}
catch( final DeploymentException de )
{
throw de;
}
catch( final Exception e )
{
throw new DeploymentException( "Error deploying library", e );
}
}
public void deployConverter( final String name, final File file )
throws DeploymentException
{
checkFile( file );
final Deployment deployment = new Deployment( file );
final Configuration descriptor = deployment.getDescriptor();
final DefaultTypeFactory factory = new DefaultTypeFactory( deployment.getURL() );
try
{
final Configuration[] converters =
descriptor.getChild( "converters" ).getChildren( "converter" );
for( int i = 0; i < converters.length; i++ )
{
if( converters[ i ].getAttribute( "classname" ).equals( name ) )
{
handleConverter( converters[ i ], factory );
break;
}
}
}
catch( final ConfigurationException ce )
{
throw new DeploymentException( "Malformed taskdefs.xml", ce );
}
catch( final Exception e )
{
throw new DeploymentException( "Failed to deploy " + name, e );
}
}
public void deployType( final String role, final String name, final File file )
throws DeploymentException
{
checkFile( file );
final String shorthand = getNameForRole( role );
final Deployment deployment = new Deployment( file );
final Configuration descriptor = deployment.getDescriptor();
final DefaultTypeFactory factory = new DefaultTypeFactory( deployment.getURL() );
try
{
final Configuration[] datatypes =
descriptor.getChild( "types" ).getChildren( shorthand );
for( int i = 0; i < datatypes.length; i++ )
{
if( datatypes[ i ].getAttribute( "name" ).equals( name ) )
{
handleType( role, datatypes[ i ], factory );
break;
}
}
}
catch( final ConfigurationException ce )
{
throw new DeploymentException( "Malformed taskdefs.xml", ce );
}
catch( final Exception e )
{
throw new DeploymentException( "Failed to deploy " + name, e );
}
}
private void deployFromDescriptor( final Configuration descriptor,
final ClassLoader classLoader,
final URL url )
throws DeploymentException, Exception
{
try
{
//Have to keep a new factory per role
//To avoid name clashes (ie a datatype and task with same name)
final HashMap factorys = new HashMap();
final Configuration[] types = descriptor.getChild( "types" ).getChildren();
for( int i = 0; i < types.length; i++ )
{
final String name = types[ i ].getName();
final String role = getRoleForName( name );
final DefaultTypeFactory factory = getFactory( role, classLoader, factorys );
handleType( role, types[ i ], factory );
}
final DefaultTypeFactory factory = new DefaultTypeFactory( classLoader );
final Configuration[] converters = descriptor.getChild( "converters" ).getChildren();
for( int i = 0; i < converters.length; i++ )
{
final String name = converters[ i ].getName();
handleConverter( converters[ i ], factory );
}
}
catch( final DeploymentException de )
{
throw de;
}
catch( final Exception e )
{
throw new DeploymentException( "Error deploying library from " + url, e );
}
}
private DefaultTypeFactory getFactory( final String role,
final ClassLoader classLoader,
final HashMap factorys )
{
DefaultTypeFactory factory = (DefaultTypeFactory)factorys.get( role );
if( null == factory )
{
factory = new DefaultTypeFactory( classLoader );
factorys.put( role, factory );
}
return factory;
}
private String getNameForRole( final String role )
throws DeploymentException
{
final String name = m_roleManager.getNameForRole( role );
if( null == name )
{
throw new DeploymentException( "RoleManager does not know name for role " + role );
}
return name;
}
private String getRoleForName( final String name )
throws DeploymentException
{
final String role = m_roleManager.getRoleForName( name );
if( null == role )
{
throw new DeploymentException( "RoleManager does not know role for name " + name );
}
return role;
}
private void checkFile( final File file )
throws DeploymentException
{
if( !file.exists() )
{
throw new DeploymentException( "Could not find application archive at " +
file );
}
if( file.isDirectory() )
{
throw new DeploymentException( "Could not find application archive at " +
file + " as it is a directory." );
}
}
private void handleConverter( final Configuration converter,
final DefaultTypeFactory factory )
throws Exception
{
final String name = converter.getAttribute( "classname" );
final String source = converter.getAttribute( "source" );
final String destination = converter.getAttribute( "destination" );
m_converterRegistry.registerConverter( name, source, destination );
factory.addNameClassMapping( name, name );
m_typeManager.registerType( Converter.ROLE, name, factory );
getLogger().debug( "Registered converter " + name + " that converts from " +
source + " to " + destination );
}
private void handleType( final String role,
final Configuration type,
final DefaultTypeFactory factory )
throws Exception
{
final String name = type.getAttribute( "name" );
final String className = type.getAttribute( "classname" );
factory.addNameClassMapping( name, className );
m_typeManager.registerType( role, name, factory );
getLogger().debug( "Registered " + role + "/" + name + " as " + className );
}
}