From 01b99d5626a6407cef6137e3f4348106cd37a98d Mon Sep 17 00:00:00 2001 From: Peter Donald Date: Thu, 31 May 2001 17:21:49 +0000 Subject: [PATCH] Started the type registry impl. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269075 13f79535-47bb-0310-9956-ffa450edef68 --- .../components/type/ComponentFactory.java | 30 +++++ .../type/DefaultComponentFactory.java | 104 ++++++++++++++++++ .../myrmidon/components/type/RoleManager.java | 86 +++++++++++++++ .../type/TypedComponentSelector.java | 101 +++++++++++++++++ 4 files changed, 321 insertions(+) create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/components/type/ComponentFactory.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/components/type/DefaultComponentFactory.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/components/type/RoleManager.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/components/type/TypedComponentSelector.java diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/ComponentFactory.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/ComponentFactory.java new file mode 100644 index 000000000..5a44f04d5 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/ComponentFactory.java @@ -0,0 +1,30 @@ +/* + * 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.type; + +import org.apache.avalon.framework.component.Component; +import org.apache.avalon.framework.component.ComponentException; + +/** + * Create a component based on role and hint. + * + * @author Peter Donald + * @version CVS $Revision$ $Date$ + */ +public interface ComponentFactory +{ + /** + * Create a Component with appropriate name. + * + * @param name the name + * @return the created component + * @exception ComponentException if an error occurs + */ + Component create( String name ) + throws ComponentException; +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/DefaultComponentFactory.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/DefaultComponentFactory.java new file mode 100644 index 000000000..30a94eaa3 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/DefaultComponentFactory.java @@ -0,0 +1,104 @@ +/* + * 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.type; + +import java.net.URL; +import java.util.HashMap; +import java.net.URLClassLoader; +import org.apache.avalon.framework.component.Component; +import org.apache.avalon.framework.component.ComponentException; + +/** + * Create a component based on name. + * + * @author Peter Donald + * @version CVS $Revision$ $Date$ + */ +public class DefaultComponentFactory + implements ComponentFactory +{ + ///A Map of shortnames to classnames + private final HashMap m_classNames = new HashMap(); + + ///A list of URLs from which classLoader is constructed + private final URL[] m_urls; + + ///The parent classLoader (if any) + private final ClassLoader m_parent; + + ///The parent classLoader (if any) + private ClassLoader m_classLoader; + + public DefaultComponentFactory( final URL[] urls ) + { + this( urls, null ); + } + + public DefaultComponentFactory( final URL[] urls, final ClassLoader parent ) + { + m_urls = urls; + m_parent = parent; + } + + public DefaultComponentFactory( final ClassLoader classLoader ) + { + this( null, null ); + m_classLoader = classLoader; + } + + public void addNameClassMapping( final String name, final String className ) + { + m_classNames.put( name, className ); + } + + /** + * Create a Component with appropriate name. + * + * @param name the name + * @return the created component + * @exception ComponentException if an error occurs + */ + public Component create( final String name ) + throws ComponentException + { + final String className = getClassName( name ); + + try + { + return (Component)getClassLoader().loadClass( className ).newInstance(); + } + catch( final Exception e ) + { + throw new ComponentException( "Unable to instantiate '" + name + "'", e ); + } + } + + private String getClassName( final String name ) + throws ComponentException + { + final String className = (String)m_classNames.get( name ); + + if( null == className ) + { + throw new ComponentException( "Malconfigured factory, no clasname for '" + + name + "'" ); + } + + return className; + } + + private ClassLoader getClassLoader() + { + if( null == m_classLoader ) + { + m_classLoader = new URLClassLoader( m_urls, m_parent ); + } + + return m_classLoader; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/RoleManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/RoleManager.java new file mode 100644 index 000000000..c87639752 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/RoleManager.java @@ -0,0 +1,86 @@ +/* + * 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.type; + +import java.util.HashMap; + +/** + * Interface to manage roles and mapping to shorthand names. + * + * @author Berin Loritsch + * @author Ricardo Rocha + * @author Giacomo Pati + * @author Peter Donald + * @version CVS $Revision$ $Date$ + */ +public class RoleManager +{ + /** Parent RoleManager for nested resolution */ + private final RoleManager m_parent; + + /** Map for shorthand to role mapping */ + private final HashMap m_shorthands = new HashMap(); + + /** + * constructor--this RoleManager has no parent. + */ + public RoleManager() + { + this( null ); + } + + /** + * Alternate constructor--this RoleManager has the specified + * parent. + * + * @param parent The parent RoleManager. + */ + public RoleManager( final RoleManager parent ) + { + m_parent = parent; + } + + /** + * Find Role name based on shorthand name. + * + * @param shorthandName the shorthand name + * @return the role + */ + public String getRoleForName( final String shorthandName ) + { + final String role = (String)m_shorthands.get( shorthandName ); + + if( null == role && null != m_parent ) + { + return m_parent.getRoleForName( shorthandName ); + } + + return role; + } + + /** + * Add a mapping between shorthand name and role + * + * @param shorthandName the shorthand name + * @param role the role + * @exception IllegalArgumentException if an name is already mapped to a different role + */ + public void addNameRoleMapping( final String shorthandName, final String role ) + throws IllegalArgumentException + { + final String oldRole = (String)m_shorthands.get( shorthandName ); + + if( null != oldRole && oldRole.equals( role ) ) + { + throw new IllegalArgumentException( "Name already mapped to another role (" + + oldRole + ")" ); + } + + m_shorthands.put( shorthandName, role ); + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/TypedComponentSelector.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/TypedComponentSelector.java new file mode 100644 index 000000000..b682b7852 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/type/TypedComponentSelector.java @@ -0,0 +1,101 @@ +/* + * 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.type; + +import java.util.HashMap; +import org.apache.avalon.framework.component.Component; +import org.apache.avalon.framework.component.ComponentSelector; +import org.apache.avalon.framework.component.ComponentException; + +/** + * This is a ComponentSelector implementation that acts as factory + * for objects and checks type on creation. + * + * @author Peter Donald + */ +public class TypedComponentSelector + implements ComponentSelector +{ + private final HashMap m_factorys = new HashMap(); + + private final Class m_type; + + public TypedComponentSelector( final Class type ) + { + m_type = type; + } + + /** + * Select the desired component. + * This creates component and checks if type appropriate. + * + * @param hint the hint to retrieve Component + * @return the Component + * @exception ComponentException if an error occurs + */ + public Component select( Object hint ) + throws ComponentException + { + if( !(hint instanceof String) ) + { + throw new ComponentException( "Invalid hint, expected a string not a " + + hint.getClass().getName() ); + } + + final Component component = createComponent( (String)hint ); + + if( null != component ) + { + if( m_type.isInstance( component ) ) + { + throw new ComponentException( "Implementation of " + hint + " is not of " + + "correct type (" + m_type.getClass().getName() + ")" ); + } + + return component; + } + else + { + throw new ComponentException( "Unable to provide implementation for " + hint ); + } + } + + /** + * Release component. + * + * @param component the component + */ + public void release( final Component component ) + { + } + + /** + * Populate the ComponentSelector. + */ + public void put( final String name, final ComponentFactory factory ) + { + m_factorys.put( name, factory ); + } + + /** + * Helper method for subclasses to retrieve component map. + * + * @return the component map + */ + private Component createComponent( final String name ) + throws ComponentException + { + final ComponentFactory factory = (ComponentFactory)m_factorys.get( name ); + + if( null == factory ) return null; + else + { + return factory.create( name ); + } + } +}