* Added ServiceManager interface, and several implementations. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271311 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -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. | |||||
| * | |||||
| * <p>This implementation uses a TypeManager to locate the service factories. | |||||
| * | |||||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
| * @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 ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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}. | |||||
| @@ -12,8 +12,8 @@ import org.apache.aut.nativelib.ExecException; | |||||
| import org.apache.aut.nativelib.impl.DefaultExecManager; | import org.apache.aut.nativelib.impl.DefaultExecManager; | ||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
| import org.apache.avalon.excalibur.i18n.Resources; | 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. | * A Factory responsible for creating the ExecManager service. | ||||
| @@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
| * @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 ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
| * @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 ); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1 @@ | |||||
| unknown-service.error=Unknown service {0}. | |||||
| @@ -5,7 +5,7 @@ | |||||
| * version 1.1, a copy of which has been included with this distribution in | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE.txt file. | * the LICENSE.txt file. | ||||
| */ | */ | ||||
| package org.apache.myrmidon.services; | |||||
| package org.apache.myrmidon.interfaces.service; | |||||
| import org.apache.avalon.framework.CascadingException; | import org.apache.avalon.framework.CascadingException; | ||||
| @@ -5,7 +5,7 @@ | |||||
| * version 1.1, a copy of which has been included with this distribution in | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE.txt file. | * 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 | * A ServiceFactory is used to create a service for use in the | ||||
| @@ -17,6 +17,8 @@ package org.apache.myrmidon.services; | |||||
| */ | */ | ||||
| public interface ServiceFactory | public interface ServiceFactory | ||||
| { | { | ||||
| String ROLE = ServiceFactory.class.getName(); | |||||
| /** | /** | ||||
| * Create a service that coresponds to this factory. | * Create a service that coresponds to this factory. | ||||
| * This method is usually called after the factory has been | * This method is usually called after the factory has been | ||||
| @@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
| * @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; | |||||
| } | |||||
| @@ -17,7 +17,7 @@ import org.apache.aut.nativelib.ExecMetaData; | |||||
| import org.apache.avalon.excalibur.io.IOUtil; | import org.apache.avalon.excalibur.io.IOUtil; | ||||
| import org.apache.myrmidon.api.TaskException; | import org.apache.myrmidon.api.TaskException; | ||||
| import org.apache.myrmidon.framework.factorys.ExecManagerFactory; | import org.apache.myrmidon.framework.factorys.ExecManagerFactory; | ||||
| import org.apache.myrmidon.services.ServiceException; | |||||
| import org.apache.myrmidon.interfaces.service.ServiceException; | |||||
| /** | /** | ||||
| * Runs an external program. | * Runs an external program. | ||||
| @@ -17,7 +17,7 @@ import org.apache.aut.nativelib.ExecMetaData; | |||||
| import org.apache.avalon.excalibur.io.IOUtil; | import org.apache.avalon.excalibur.io.IOUtil; | ||||
| import org.apache.myrmidon.api.TaskException; | import org.apache.myrmidon.api.TaskException; | ||||
| import org.apache.myrmidon.framework.factorys.ExecManagerFactory; | import org.apache.myrmidon.framework.factorys.ExecManagerFactory; | ||||
| import org.apache.myrmidon.services.ServiceException; | |||||
| import org.apache.myrmidon.interfaces.service.ServiceException; | |||||
| /** | /** | ||||
| * Runs an external program. | * Runs an external program. | ||||