From 56250d886e6efcfa207e9c1f2cd4b00985e259fd Mon Sep 17 00:00:00 2001 From: adammurdoch Date: Thu, 14 Feb 2002 02:03:25 +0000 Subject: [PATCH] * Moved package org.apache.myrmidon.services to org.apache.myrmidon.interfaces.service. * Added ServiceManager interface, and several implementations. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271311 13f79535-47bb-0310-9956-ffa450edef68 --- .../service/DefaultServiceManager.java | 144 ++++++++++++++++++ .../components/service/Resources.properties | 3 + .../factorys/ExecManagerFactory.java | 4 +- .../service/ComponentManagerAdaptor.java | 52 +++++++ .../service/MultiSourceServiceManager.java | 79 ++++++++++ .../interfaces/service/Resources.properties | 1 + .../service}/ServiceException.java | 2 +- .../service}/ServiceFactory.java | 4 +- .../interfaces/service/ServiceManager.java | 40 +++++ .../tools/ant/taskdefs/exec/Execute.java | 2 +- .../tools/ant/taskdefs/exec/Execute.java | 2 +- 11 files changed, 327 insertions(+), 6 deletions(-) create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultServiceManager.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ComponentManagerAdaptor.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/Resources.properties rename proposal/myrmidon/src/java/org/apache/myrmidon/{services => interfaces/service}/ServiceException.java (96%) rename proposal/myrmidon/src/java/org/apache/myrmidon/{services => interfaces/service}/ServiceFactory.java (89%) create mode 100644 proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceManager.java diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultServiceManager.java new file mode 100644 index 000000000..8d25ff1c2 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/DefaultServiceManager.java @@ -0,0 +1,144 @@ +/* + * 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.txt file. + */ +package org.apache.myrmidon.components.service; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.apache.avalon.excalibur.i18n.ResourceManager; +import org.apache.avalon.excalibur.i18n.Resources; +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.component.ComponentException; +import org.apache.avalon.framework.component.ComponentManager; +import org.apache.avalon.framework.component.Composable; +import org.apache.myrmidon.interfaces.service.ServiceException; +import org.apache.myrmidon.interfaces.service.ServiceFactory; +import org.apache.myrmidon.interfaces.service.ServiceManager; +import org.apache.myrmidon.interfaces.type.TypeException; +import org.apache.myrmidon.interfaces.type.TypeFactory; +import org.apache.myrmidon.interfaces.type.TypeManager; + +/** + * A service manager implementation. This implementation takes care of + * creating service instances, using a {@link ServiceFactory}, and running the + * service instances through the service lifecycle. Service creation happens + * on demand. + * + *

This implementation uses a TypeManager to locate the service factories. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class DefaultServiceManager + implements ServiceManager, Composable, Disposable +{ + private final static Resources REZ + = ResourceManager.getPackageResources( DefaultServiceManager.class ); + + /** Map from service class -> service object. */ + private Map m_services = new HashMap(); + + private TypeFactory m_typeFactory; + + /** + * Locate the components used by this service manager. + */ + public void compose( final ComponentManager componentManager ) throws ComponentException + { + final TypeManager typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE ); + try + { + m_typeFactory = typeManager.getFactory( ServiceFactory.class ); + } + catch( final TypeException e ) + { + throw new ComponentException( e.getMessage(), e ); + } + } + + /** + * Disposes this service manager, and all services created by it. + */ + public void dispose() + { + // Dispose the services + for( Iterator iterator = m_services.values().iterator(); iterator.hasNext(); ) + { + final Object object = iterator.next(); + if( object instanceof Disposable ) + { + ( (Disposable)object ).dispose(); + } + } + + // Ditch state + m_services = null; + m_typeFactory = null; + } + + /** + * Determines if this service manager contains a particular service. + */ + public boolean hasService( Class serviceType ) + { + // If we have already instantiated the service, or if we know how + // to instantiate it, then return true + if( m_services.containsKey( serviceType ) ) + { + return true; + } + if( m_typeFactory.canCreate( serviceType.getName() ) ) + { + return true; + } + + return false; + } + + /** + * Locates a service instance. + */ + public Object getService( Class serviceType ) + throws ServiceException + { + Object service = m_services.get( serviceType ); + if( service == null ) + { + // Create the service + service = createService( serviceType ); + m_services.put( serviceType, service ); + } + + return service; + } + + /** + * Creates the service object for a service class. + */ + private Object createService( Class serviceType ) throws ServiceException + { + try + { + final ServiceFactory factory = (ServiceFactory)m_typeFactory.create( serviceType.getName() ); + + // Create the service + final Object service = factory.createService(); + if( ! serviceType.isInstance( service ) ) + { + final String message = REZ.getString( "mismatched-service-type.error", serviceType.getName(), service.getClass().getName() ); + throw new ServiceException( message ); + } + return service; + } + catch( Exception e ) + { + final String message = REZ.getString( "create-service.error", serviceType.getName() ); + throw new ServiceException( message, e ); + } + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties new file mode 100644 index 000000000..09d9d6492 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties @@ -0,0 +1,3 @@ +unknown-service-type.error=Unknown service type {0}. +mismatched-service-type.error=Service factory for type {0} produced an object of unexpected type {1}. +create-service.error=Could not create service {0}. \ No newline at end of file diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factorys/ExecManagerFactory.java b/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factorys/ExecManagerFactory.java index cefdff914..0b6d3a189 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factorys/ExecManagerFactory.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/framework/factorys/ExecManagerFactory.java @@ -12,8 +12,8 @@ import org.apache.aut.nativelib.ExecException; import org.apache.aut.nativelib.impl.DefaultExecManager; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; -import org.apache.myrmidon.services.ServiceException; -import org.apache.myrmidon.services.ServiceFactory; +import org.apache.myrmidon.interfaces.service.ServiceException; +import org.apache.myrmidon.interfaces.service.ServiceFactory; /** * A Factory responsible for creating the ExecManager service. diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ComponentManagerAdaptor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ComponentManagerAdaptor.java new file mode 100644 index 000000000..a8eb3a686 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ComponentManagerAdaptor.java @@ -0,0 +1,52 @@ +/* + * 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.txt file. + */ +package org.apache.myrmidon.interfaces.service; + +import org.apache.avalon.framework.component.ComponentException; +import org.apache.avalon.framework.component.ComponentManager; + +/** + * An adaptor from {@link ComponentManager} to {@link ServiceManager}. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class ComponentManagerAdaptor + implements ServiceManager +{ + private final ComponentManager m_componentManager; + + public ComponentManagerAdaptor( final ComponentManager componentManager ) + { + m_componentManager = componentManager; + } + + /** + * Determines if this service manager contains a particular service. + */ + public boolean hasService( Class serviceType ) + { + return m_componentManager.hasComponent( serviceType.getName() ); + } + + /** + * Locates a service instance. + */ + public Object getService( Class serviceType ) + throws ServiceException + { + try + { + return m_componentManager.lookup( serviceType.getName() ); + } + catch( ComponentException e ) + { + throw new ServiceException( e.getMessage(), e ); + } + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java new file mode 100644 index 000000000..4b4f9d431 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/MultiSourceServiceManager.java @@ -0,0 +1,79 @@ +/* + * 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.txt file. + */ +package org.apache.myrmidon.interfaces.service; + +import java.util.ArrayList; +import org.apache.avalon.excalibur.i18n.ResourceManager; +import org.apache.avalon.excalibur.i18n.Resources; + +/** + * A service manager that aggregates services from several + * {@link ServiceManager} objects. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public class MultiSourceServiceManager + implements ServiceManager +{ + private final static Resources REZ + = ResourceManager.getPackageResources( MultiSourceServiceManager.class ); + + /** The source service managers, in order. */ + private final ArrayList m_sources = new ArrayList(); + + /** + * Adds a service manager to the end of the source list. + */ + public void add( final ServiceManager mgr ) + { + m_sources.add( mgr ); + } + + /** + * Determines if this service manager contains a particular service. + * + * @param serviceType The service interface. + */ + public boolean hasService( Class serviceType ) + { + for( int i = 0; i < m_sources.size(); i++ ) + { + final ServiceManager serviceManager = (ServiceManager)m_sources.get( i ); + if( serviceManager.hasService( serviceType ) ) + { + return true; + } + } + return false; + } + + /** + * Locates a service instance. + * + * @param serviceType The service interface. + * @return The service instance. The returned object is guaranteed to + * implement the service interface. + * @throws ServiceException If the service does not exist. + */ + public Object getService( Class serviceType ) + throws ServiceException + { + for( int i = 0; i < m_sources.size(); i++ ) + { + final ServiceManager serviceManager = (ServiceManager)m_sources.get( i ); + if( serviceManager.hasService( serviceType ) ) + { + return serviceManager.getService( serviceType ); + } + } + + final String message = REZ.getString( "unknown-service.error", serviceType.getName() ); + throw new ServiceException( message ); + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/Resources.properties new file mode 100644 index 000000000..68e97de95 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/Resources.properties @@ -0,0 +1 @@ +unknown-service.error=Unknown service {0}. \ No newline at end of file diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/services/ServiceException.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceException.java similarity index 96% rename from proposal/myrmidon/src/java/org/apache/myrmidon/services/ServiceException.java rename to proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceException.java index 175b9f7f8..c5f4f620d 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/services/ServiceException.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceException.java @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ -package org.apache.myrmidon.services; +package org.apache.myrmidon.interfaces.service; import org.apache.avalon.framework.CascadingException; diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/services/ServiceFactory.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java similarity index 89% rename from proposal/myrmidon/src/java/org/apache/myrmidon/services/ServiceFactory.java rename to proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java index 8fd15ac44..c5453b448 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/services/ServiceFactory.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceFactory.java @@ -5,7 +5,7 @@ * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ -package org.apache.myrmidon.services; +package org.apache.myrmidon.interfaces.service; /** * A ServiceFactory is used to create a service for use in the @@ -17,6 +17,8 @@ package org.apache.myrmidon.services; */ public interface ServiceFactory { + String ROLE = ServiceFactory.class.getName(); + /** * Create a service that coresponds to this factory. * This method is usually called after the factory has been diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceManager.java new file mode 100644 index 000000000..394c7aa4c --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/service/ServiceManager.java @@ -0,0 +1,40 @@ +/* + * 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.txt file. + */ +package org.apache.myrmidon.interfaces.service; + +import org.apache.avalon.framework.component.Component; + +/** + * Manages a set of services. + * + * @author Adam Murdoch + * @version $Revision$ $Date$ + */ +public interface ServiceManager + extends Component +{ + String ROLE = ServiceManager.class.getName(); + + /** + * Determines if this service manager contains a particular service. + * + * @param serviceType The service interface. + */ + boolean hasService( Class serviceType ); + + /** + * Locates a service instance. + * + * @param serviceType The service interface. + * @return The service instance. The returned object is guaranteed to + * implement the service interface. + * @throws ServiceException If the service does not exist. + */ + Object getService( Class serviceType ) + throws ServiceException; +} diff --git a/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/Execute.java b/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/Execute.java index 7bf2af3dc..06398326b 100644 --- a/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/Execute.java +++ b/proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/exec/Execute.java @@ -17,7 +17,7 @@ import org.apache.aut.nativelib.ExecMetaData; import org.apache.avalon.excalibur.io.IOUtil; import org.apache.myrmidon.api.TaskException; import org.apache.myrmidon.framework.factorys.ExecManagerFactory; -import org.apache.myrmidon.services.ServiceException; +import org.apache.myrmidon.interfaces.service.ServiceException; /** * Runs an external program. diff --git a/proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/exec/Execute.java b/proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/exec/Execute.java index 7bf2af3dc..06398326b 100644 --- a/proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/exec/Execute.java +++ b/proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/exec/Execute.java @@ -17,7 +17,7 @@ import org.apache.aut.nativelib.ExecMetaData; import org.apache.avalon.excalibur.io.IOUtil; import org.apache.myrmidon.api.TaskException; import org.apache.myrmidon.framework.factorys.ExecManagerFactory; -import org.apache.myrmidon.services.ServiceException; +import org.apache.myrmidon.interfaces.service.ServiceException; /** * Runs an external program.