* 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. | ||||