hlship 2004/12/19 07:43:08
Modified: framework/src/java/org/apache/hivemind/impl
ConstructableServicePoint.java
ServicePointImpl.java
RegistryInfrastructureConstructor.java
framework/src/java/org/apache/hivemind/parse
AbstractServiceDescriptor.java
ImplementationDescriptor.java
framework/src/test/org/apache/hivemind/test
TestMockClass.java
Added: framework/src/test/org/apache/hivemind/impl
TestServicePoint.java
Log:
Add support for overriding default service implementations.
Revision Changes Path
1.1
jakarta-hivemind/framework/src/test/org/apache/hivemind/impl/TestServicePoint.java
Index: TestServicePoint.java
===================================================================
package org.apache.hivemind.impl;
import java.util.ArrayList;
import java.util.Map;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Location;
import org.apache.hivemind.internal.Module;
import org.apache.hivemind.internal.ServiceModel;
import org.apache.hivemind.internal.ServiceModelFactory;
import org.apache.hivemind.test.HiveMindTestCase;
import org.easymock.MockControl;
/**
* Test for [EMAIL PROTECTED] org.apache.hivemind.impl.ServicePointImpl}.
Much of the testing is done using
* integration style tests, this just fills in some important gaps.
*
* @author Howard M. Lewis Ship
* @since 1.1
*/
public class TestServicePoint extends HiveMindTestCase
{
private Module newModule()
{
MockControl control = newControl(Module.class);
Module module = (Module) control.getMock();
module.getClassResolver();
control.setReturnValue(new DefaultClassResolver());
return module;
}
public void testUnknownInterfaceClass()
{
Location l = fabricateLocation(12);
Module module = newModule();
replayControls();
ServicePointImpl sp = new ServicePointImpl();
sp.setModule(module);
sp.setServiceInterfaceName("foo.bar.Baz");
sp.setExtensionPointId("zip.zap");
sp.setLocation(l);
try
{
sp.getServiceInterface();
unreachable();
}
catch (ApplicationRuntimeException ex)
{
assertEquals("Unable to find interface foo.bar.Baz (for service
zip.zap).", ex
.getMessage());
assertSame(l, ex.getLocation());
}
verifyControls();
}
public void testNotAnInterface()
{
Location l = fabricateLocation(12);
Module module = newModule();
replayControls();
ServicePointImpl sp = new ServicePointImpl();
sp.setModule(module);
sp.setServiceInterfaceName("java.util.ArrayList");
sp.setExtensionPointId("zip.zap");
sp.setLocation(l);
try
{
sp.getServiceInterface();
unreachable();
}
catch (ApplicationRuntimeException ex)
{
assertEquals(
"Service points must provide an interface type:
java.util.ArrayList is a class (for service zip.zap).",
ex.getMessage());
assertSame(l, ex.getLocation());
}
verifyControls();
}
public void testResultNotAssignableToServiceInterface()
{
Location l = fabricateLocation(187);
ServicePointImpl sp = new ServicePointImpl();
MockControl modulec = newControl(Module.class);
Module module = (Module) modulec.getMock();
Object service = new ArrayList();
MockControl factoryc = newControl(ServiceModelFactory.class);
ServiceModelFactory factory = (ServiceModelFactory)
factoryc.getMock();
MockControl modelc = newControl(ServiceModel.class);
ServiceModel model = (ServiceModel) modelc.getMock();
module.getServiceModelFactory("fred");
modulec.setReturnValue(factory);
factory.createServiceModelForService(sp);
factoryc.setReturnValue(model);
model.getService();
modelc.setReturnValue(service);
module.getClassResolver();
modulec.setReturnValue(new DefaultClassResolver());
replayControls();
sp.setExtensionPointId("foo.bar");
sp.setServiceInterfaceName("java.util.List");
sp.setLocation(l);
sp.setModule(module);
sp.setServiceModel("fred");
try
{
sp.getService(Map.class);
unreachable();
}
catch (ApplicationRuntimeException ex)
{
assertEquals(
"Service foo.bar does not implement the requested
interface (java.util.Map). The declared service interface type is
java.util.List.",
ex.getMessage());
assertSame(l, ex.getLocation());
}
}
}
1.3 +39 -39
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ConstructableServicePoint.java
Index: ConstructableServicePoint.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ConstructableServicePoint.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ConstructableServicePoint.java 17 Jun 2004 15:16:12 -0000 1.2
+++ ConstructableServicePoint.java 19 Dec 2004 15:43:07 -0000 1.3
@@ -21,66 +21,66 @@
import org.apache.hivemind.internal.ServiceImplementationConstructor;
/**
- * "Private" interface used by a [EMAIL PROTECTED]
org.apache.hivemind.ServiceModel}
- * to access non-public information about a
- * [EMAIL PROTECTED] ConstructableServicePoint}, such as
- * its instance builder and interceptors.
- *
+ * "Private" interface used by a [EMAIL PROTECTED]
org.apache.hivemind.ServiceModel}to access non-public
+ * information about a [EMAIL PROTECTED] ConstructableServicePoint}, such as
its instance builder and
+ * interceptors.
+ *
* @author Howard Lewis Ship
*/
public interface ConstructableServicePoint extends ServicePoint
{
- /**
- * Returns the constructor that can create the core service
implementation.
- */
+ /**
+ * Returns the constructor that can create the core service
implementation. Returns the service
+ * constructor, if defined, or the default service constructor. The
default service constructor
+ * comes from the <service-point> itself; other modules can
override this default using an
+ * <implementation> element.
+ */
public ServiceImplementationConstructor getServiceConstructor();
/**
- * Returns a list of [EMAIL PROTECTED]
org.apache.hivemind.ServiceInterceptorContribution}s,
- * ordered according to their dependencies. May return null or an empty
list.
- *
+ * Returns a list of [EMAIL PROTECTED]
org.apache.hivemind.ServiceInterceptorContribution}s, ordered
+ * according to their dependencies. May return null or an empty list.
* <p>
- * Note that the order is tricky! To keep any error messages while
ordering
- * the interceptors understandable, they are ordered according into
runtime
- * execution order. Example: If we want a logging interceptor
- * to operate before a security-check interceptor, we'll write the
following
- * in the descriptor:
+ * Note that the order is tricky! To keep any error messages while
ordering the interceptors
+ * understandable, they are ordered according into runtime execution
order. Example: If we want
+ * a logging interceptor to operate before a security-check interceptor,
we'll write the
+ * following in the descriptor:
*
* <pre>
- * <interceptor service-id="hivemind.LoggingInterceptor"
before="*"/>
- * <interceptor service-id="somepackage.SecurityInterceptor"/>
+ *
+ *
+ * <interceptor
service-id="hivemind.LoggingInterceptor" before="*"/>
+ * <interceptor
service-id="somepackage.SecurityInterceptor"/>
+ *
+ *
* </pre>
*
- * The <code>before</code> value for the first interceptor contribution
- * will be assigned to the contribution's
+ * The <code>before</code> value for the first interceptor contribution
will be assigned to
+ * the contribution's
* [EMAIL PROTECTED]
org.apache.hivemind.ServiceInterceptorContribution#getFollowingInterceptorIds()
followingInterceptorIds}
- * property, because all other interceptors (including the security
interceptor)
- * should have their behavior follow the logging interceptor.
- *
+ * property, because all other interceptors (including the security
interceptor) should have
+ * their behavior follow the logging interceptor.
* <p>
- * To get this behavior, the logging interceptor will delegate to the
security
- * interceptor, and the security interceptor will delegate to
- * the core service implementation.
- *
+ * To get this behavior, the logging interceptor will delegate to the
security interceptor, and
+ * the security interceptor will delegate to the core service
implementation.
* <p>
- * The trick is that interceptors are applied in reverse order: we start
- * with core service implementation, wrap it with the security
interceptor, then
- * wrap that with the logging interceptor ... but that's an issue that
applies
- * when building the interceptor stack around the core service
implementation.
+ * The trick is that interceptors are applied in reverse order: we start
with core service
+ * implementation, wrap it with the security interceptor, then wrap that
with the logging
+ * interceptor ... but that's an issue that applies when building the
interceptor stack around
+ * the core service implementation.
*/
public List getOrderedInterceptorContributions();
/**
- * Invoked by the ServiceModel when constuction information
- * (the builder and interceptors) is no longer needed.
+ * Invoked by the ServiceModel when constuction information (the builder
and interceptors) is no
+ * longer needed.
*/
public void clearConstructorInformation();
-
+
/**
- * Returns the [EMAIL PROTECTED] ShutdownCooordinator}, used by
- * the service model to inform proxies that the service
- * has shutdown.
+ * Returns the [EMAIL PROTECTED] ShutdownCooordinator}, used by the
service model to inform proxies that
+ * the service has shutdown.
*/
-
+
public ShutdownCoordinator getShutdownCoordinator();
-}
+}
\ No newline at end of file
1.8 +59 -42
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ServicePointImpl.java
Index: ServicePointImpl.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/ServicePointImpl.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ServicePointImpl.java 2 Nov 2004 17:46:09 -0000 1.7
+++ ServicePointImpl.java 19 Dec 2004 15:43:07 -0000 1.8
@@ -34,28 +34,39 @@
import org.apache.hivemind.util.ToStringBuilder;
/**
- * Abstract implementation of [EMAIL PROTECTED]
org.apache.hivemind.internal.ServicePoint}.
- * Provides some of the machinery for creating new service instances,
delegating
- * most of it to the [EMAIL PROTECTED]
org.apache.hivemind.internal.ServiceModel} instace
- * for the service.
- *
+ * Abstract implementation of [EMAIL PROTECTED]
org.apache.hivemind.internal.ServicePoint}. Provides some of
+ * the machinery for creating new service instances, delegating most of it
to the
+ * [EMAIL PROTECTED] org.apache.hivemind.internal.ServiceModel}instace for
the service.
+ *
* @author Howard Lewis Ship
*/
-public final class ServicePointImpl
- extends AbstractExtensionPoint
- implements ConstructableServicePoint
+public final class ServicePointImpl extends AbstractExtensionPoint implements
+ ConstructableServicePoint
{
private Object _service;
+
private boolean _building;
+
private String _serviceInterfaceName;
+
private Class _serviceInterface;
+
+ private ServiceImplementationConstructor _defaultServiceConstructor;
+
private ServiceImplementationConstructor _serviceConstructor;
+
private List _interceptorContributions;
+
private boolean _interceptorsOrdered;
+
private Schema _parametersSchema;
+
private Occurances _parametersCount;
+
private String _serviceModel;
+
private ShutdownCoordinator _shutdownCoordinator;
+
private ServiceModel _serviceModelObject;
protected void extendDescription(ToStringBuilder builder)
@@ -64,7 +75,8 @@
builder.append("service", _service);
builder.append("serviceInterfaceName", _serviceInterfaceName);
- builder.append("factoryContribution", _serviceConstructor);
+ builder.append("defaultServiceConstructor",
_defaultServiceConstructor);
+ builder.append("serviceConstructor", _serviceConstructor);
builder.append("interceptorContributions",
_interceptorContributions);
builder.append("parametersSchema", _parametersSchema);
builder.append("parametersCount", _parametersCount);
@@ -101,24 +113,26 @@
}
catch (Exception ex)
{
- throw new ApplicationRuntimeException(
- ImplMessages.badInterface(_serviceInterfaceName,
getExtensionPointId()),
- getLocation(),
- ex);
+ throw new ApplicationRuntimeException(ImplMessages.badInterface(
+ _serviceInterfaceName,
+ getExtensionPointId()), getLocation(), ex);
}
if (!result.isInterface())
- throw new ApplicationRuntimeException(
- ImplMessages.interfaceRequired(_serviceInterfaceName,
getExtensionPointId()),
- getLocation(),
- null);
+ throw new
ApplicationRuntimeException(ImplMessages.interfaceRequired(
+ _serviceInterfaceName,
+ getExtensionPointId()), getLocation(), null);
return result;
}
- public void setServiceConstructor(ServiceImplementationConstructor
contribution)
+ public void setServiceConstructor(ServiceImplementationConstructor
contribution,
+ boolean defaultConstructor)
{
- _serviceConstructor = contribution;
+ if (defaultConstructor)
+ _defaultServiceConstructor = contribution;
+ else
+ _serviceConstructor = contribution;
}
public void setServiceInterfaceName(String string)
@@ -136,20 +150,17 @@
return _parametersSchema;
}
- public ServiceImplementationConstructor getServiceConstructor()
+ public ServiceImplementationConstructor getServiceConstructor(boolean
defaultConstructor)
{
- return _serviceConstructor;
+ return defaultConstructor ? _defaultServiceConstructor :
_serviceConstructor;
}
/**
- * Invoked by [EMAIL PROTECTED] #getService(Class)} to get a service
implementation
- * from the [EMAIL PROTECTED] ServiceModel}.
- *
+ * Invoked by [EMAIL PROTECTED] #getService(Class)}to get a service
implementation from the
+ * [EMAIL PROTECTED] ServiceModel}.
* <p>
- * TODO: I'm concerned that this synchronized method could cause a
deadlock. It would take
- * a LOT (mutually dependent services in multiple threads being realized
at the same time).
- *
- *
+ * TODO: I'm concerned that this synchronized method could cause a
deadlock. It would take a LOT
+ * (mutually dependent services in multiple threads being realized at
the same time).
*/
private synchronized Object getService()
{
@@ -185,10 +196,9 @@
if (!serviceInterface.isAssignableFrom(result.getClass()))
{
- throw new ApplicationRuntimeException(
- ImplMessages.serviceWrongInterface(this, serviceInterface),
- getLocation(),
- null);
+ throw new
ApplicationRuntimeException(ImplMessages.serviceWrongInterface(
+ this,
+ serviceInterface), getLocation(), null);
}
return result;
@@ -233,23 +243,20 @@
Log log = LogFactory.getLog(getExtensionPointId());
- Orderer orderer =
- new Orderer(log, getModule().getErrorHandler(),
ImplMessages.interceptorContribution());
+ Orderer orderer = new Orderer(log, getModule().getErrorHandler(),
ImplMessages
+ .interceptorContribution());
Iterator i = _interceptorContributions.iterator();
while (i.hasNext())
{
ServiceInterceptorContribution sic =
(ServiceInterceptorContribution) i.next();
- // Sort them into runtime excecution order. When we build
+ // Sort them into runtime excecution order. When we build
// the interceptor stack we'll apply them in reverse order,
// building outward from the core service implementation.
- orderer.add(
- sic,
- sic.getFactoryServiceId(),
- sic.getPrecedingInterceptorIds(),
- sic.getFollowingInterceptorIds());
+ orderer.add(sic, sic.getFactoryServiceId(),
sic.getPrecedingInterceptorIds(), sic
+ .getFollowingInterceptorIds());
}
return orderer.getOrderedObjects();
@@ -274,7 +281,7 @@
_serviceModelObject.instantiateService();
}
-
+
public Occurances getParametersCount()
{
return _parametersCount;
@@ -285,4 +292,14 @@
_parametersCount = occurances;
}
-}
+ /**
+ * Returns the service constructor, if defined, or the default service
constructor. The default
+ * service constructor comes from the <service-point> itself;
other modules can override
+ * this default using an <implementation> element.
+ */
+
+ public ServiceImplementationConstructor getServiceConstructor()
+ {
+ return _serviceConstructor == null ? _defaultServiceConstructor :
_serviceConstructor;
+ }
+}
\ No newline at end of file
1.7 +13 -10
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/RegistryInfrastructureConstructor.java
Index: RegistryInfrastructureConstructor.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/RegistryInfrastructureConstructor.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- RegistryInfrastructureConstructor.java 17 Nov 2004 11:30:04 -0000
1.6
+++ RegistryInfrastructureConstructor.java 19 Dec 2004 15:43:07 -0000
1.7
@@ -512,7 +512,7 @@
return;
if (builder != null)
- addServiceInstanceBuilder(sourceModule, pointId, builder);
+ addServiceInstanceBuilder(sourceModule, pointId, builder, true);
if (interceptors == null)
return;
@@ -536,7 +536,7 @@
List interceptors = id.getInterceptors();
if (builder != null)
- addServiceInstanceBuilder(sourceModule, pointId, builder);
+ addServiceInstanceBuilder(sourceModule, pointId, builder, false);
int count = size(interceptors);
for (int i = 0; i < count; i++)
@@ -550,7 +550,7 @@
* Adds an [EMAIL PROTECTED] InstanceBuilder}to a service extension
point.
*/
private void addServiceInstanceBuilder(Module sourceModule, String
pointId,
- InstanceBuilder builder)
+ InstanceBuilder builder, boolean isDefault)
{
if (_log.isDebugEnabled())
_log.debug("Adding " + builder + " to service extension point "
+ pointId);
@@ -567,29 +567,32 @@
return;
}
- if (point.getServiceConstructor() != null)
+ if (!point.visibleToModule(sourceModule))
{
_errorHandler.error(
_log,
- ImplMessages.duplicateFactory(sourceModule, pointId,
point),
+ ImplMessages.servicePointNotVisible(point, sourceModule),
builder.getLocation(),
null);
-
return;
}
- if (!point.visibleToModule(sourceModule))
+
+
+ if (point.getServiceConstructor(isDefault) != null)
{
_errorHandler.error(
_log,
- ImplMessages.servicePointNotVisible(point, sourceModule),
+ ImplMessages.duplicateFactory(sourceModule, pointId,
point),
builder.getLocation(),
null);
+
return;
}
-
+
+
point.setServiceModel(builder.getServiceModel());
- point.setServiceConstructor(builder.createConstructor(point,
sourceModule));
+ point.setServiceConstructor(builder.createConstructor(point,
sourceModule), isDefault);
}
private void addInterceptor(Module sourceModule, String pointId,
InterceptorDescriptor id)
1.5 +2 -1
jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/AbstractServiceDescriptor.java
Index: AbstractServiceDescriptor.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/AbstractServiceDescriptor.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AbstractServiceDescriptor.java 14 Oct 2004 14:31:30 -0000 1.4
+++ AbstractServiceDescriptor.java 19 Dec 2004 15:43:07 -0000 1.5
@@ -30,6 +30,7 @@
{
private InstanceBuilder _instanceBuilder;
private List _interceptors;
+
public String toString()
{
@@ -42,7 +43,7 @@
return builder.toString();
}
-
+
/**
* Implemented in subclasses to provide details about the instance.
*/
1.4 +2 -3
jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/ImplementationDescriptor.java
Index: ImplementationDescriptor.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/ImplementationDescriptor.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ImplementationDescriptor.java 25 Jun 2004 20:20:02 -0000 1.3
+++ ImplementationDescriptor.java 19 Dec 2004 15:43:07 -0000 1.4
@@ -18,7 +18,7 @@
/**
* Descriptor for <implementation> elements.
- *
+ *
* @author Howard Lewis Ship
*/
public final class ImplementationDescriptor extends AbstractServiceDescriptor
@@ -39,5 +39,4 @@
{
builder.append("serviceId", _serviceId);
}
-
-}
+}
\ No newline at end of file
1.2 +1 -1
jakarta-hivemind/framework/src/test/org/apache/hivemind/test/TestMockClass.java
Index: TestMockClass.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/test/org/apache/hivemind/test/TestMockClass.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TestMockClass.java 5 Dec 2004 16:43:19 -0000 1.1
+++ TestMockClass.java 19 Dec 2004 15:43:07 -0000 1.2
@@ -1,4 +1,4 @@
-//Copyright 2004 The Apache Software Foundation
+// Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]