* 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.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. | |||
| @@ -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 | |||
| * the LICENSE.txt file. | |||
| */ | |||
| package org.apache.myrmidon.services; | |||
| package org.apache.myrmidon.interfaces.service; | |||
| import org.apache.avalon.framework.CascadingException; | |||
| @@ -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 | |||
| @@ -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.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. | |||
| @@ -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. | |||