hlship 2004/09/14 10:48:26
Modified: . Tag: branch-1-0 status.xml
library/src/java/org/apache/hivemind/lib/impl Tag:
branch-1-0 ServicePropertyFactory.java
framework/src/java/org/apache/hivemind/service/impl Tag:
branch-1-0 LoggingInterceptorFactory.java
framework/src/java/org/apache/hivemind/service Tag:
branch-1-0 ClassFabUtils.java
Added: framework/src/test/org/apache/hivemind/service/impl Tag:
branch-1-0 TestLoggingInterceptorFactory.java
TestClassFabUtils.java
Log:
HIVEMIND-55: Make fabricated classes work with JDK proxies.
Revision Changes Path
No revision
No revision
1.1.2.1 +97 -0
jakarta-hivemind/framework/src/test/org/apache/hivemind/service/impl/Attic/TestLoggingInterceptorFactory.java
1.1.2.1 +42 -0
jakarta-hivemind/framework/src/test/org/apache/hivemind/service/impl/Attic/TestClassFabUtils.java
No revision
No revision
1.57.2.8 +6 -0 jakarta-hivemind/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/status.xml,v
retrieving revision 1.57.2.7
retrieving revision 1.57.2.8
diff -u -r1.57.2.7 -r1.57.2.8
--- status.xml 11 Sep 2004 13:06:51 -0000 1.57.2.7
+++ status.xml 14 Sep 2004 17:48:25 -0000 1.57.2.8
@@ -30,6 +30,12 @@
<changes>
+ <release version="1.0" date="unreleased">
+ <action type="fix" dev="HLS" fixes-bug="HIVEMIND-55">
+ Ensure that the logging interceptor will work properly when wrapping
around JDK dynamic proxies.
+ </action>
+ </release>
+
<release version="1.0-rc-2" date="Sep 11 2004">
<action type="add" dev="HLS">
Add method <code>getSymbolValue()</code> to RegistryInfrastructure
and Module
No revision
No revision
1.4.2.2 +26 -61
jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ServicePropertyFactory.java
Index: ServicePropertyFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/library/src/java/org/apache/hivemind/lib/impl/ServicePropertyFactory.java,v
retrieving revision 1.4.2.1
retrieving revision 1.4.2.2
diff -u -r1.4.2.1 -r1.4.2.2
--- ServicePropertyFactory.java 7 Sep 2004 19:38:27 -0000 1.4.2.1
+++ ServicePropertyFactory.java 14 Sep 2004 17:48:25 -0000 1.4.2.2
@@ -32,23 +32,19 @@
import org.apache.hivemind.util.PropertyUtils;
/**
- * Factory that dynamically exposes a property of another service. A proxy
- * is constructed that accesses the target service and obtains a property
from that.
- * The service interface of the constructed service must match the
- * type of the exposed property.
- *
+ * Factory that dynamically exposes a property of another service. A proxy is
+ * constructed that accesses the target service and obtains a property from
+ * that. The service interface of the constructed service must match the
type of
+ * the exposed property.
+ *
* @author Howard Lewis Ship
*/
public class ServicePropertyFactory implements ServiceImplementationFactory
{
private ClassFactory _classFactory;
- public Object createCoreServiceImplementation(
- String serviceId,
- Class serviceInterface,
- Log serviceLog,
- Module invokingModule,
- List parameters)
+ public Object createCoreServiceImplementation(String serviceId, Class
serviceInterface, Log serviceLog,
+ Module invokingModule, List parameters)
{
ServicePropertyFactoryParameter p =
(ServicePropertyFactoryParameter) parameters.get(0);
@@ -60,31 +56,18 @@
String readMethodName = pa.getReadMethodName();
if (readMethodName == null)
- throw new ApplicationRuntimeException(
- ImplMessages.servicePropertyNotReadable(propertyName,
targetService),
- null,
- p.getLocation(),
- null);
+ throw new
ApplicationRuntimeException(ImplMessages.servicePropertyNotReadable(propertyName,
targetService),
+ null, p.getLocation(), null);
if (!(serviceInterface.isAssignableFrom(pa.getPropertyType())))
- throw new ApplicationRuntimeException(
- ImplMessages.servicePropertyWrongType(
- propertyName,
- targetService,
- pa.getPropertyType(),
- serviceInterface),
- p.getLocation(),
- null);
+ throw new
ApplicationRuntimeException(ImplMessages.servicePropertyWrongType(propertyName,
targetService, pa
+ .getPropertyType(), serviceInterface), p.getLocation(),
null);
// Now we're good to go.
String name =
ClassFabUtils.generateClassName("ServicePropertyProxy");
- ClassFab cf =
- _classFactory.newClass(
- name,
- Object.class,
- invokingModule.getClassResolver().getClassLoader());
+ ClassFab cf = _classFactory.newClass(name, Object.class,
invokingModule.getClassResolver().getClassLoader());
addInfrastructure(cf, targetService, serviceInterface, propertyName,
readMethodName);
@@ -94,7 +77,8 @@
try
{
- return ConstructorUtils.invokeConstructor(proxyClass, new
Object[] { targetService });
+ return ConstructorUtils.invokeConstructor(proxyClass, new
Object[]
+ { targetService });
}
catch (Throwable ex)
{
@@ -102,31 +86,22 @@
}
}
- private void addInfrastructure(
- ClassFab cf,
- Object targetService,
- Class serviceInterface,
- String propertyName,
- String readPropertyMethodName)
+ private void addInfrastructure(ClassFab cf, Object targetService, Class
serviceInterface, String propertyName,
+ String readPropertyMethodName)
{
cf.addInterface(serviceInterface);
- Class targetServiceClass = targetService.getClass();
+ Class targetServiceClass =
ClassFabUtils.getInstanceClass(targetService, serviceInterface);
cf.addField("_targetService", targetServiceClass);
- cf.addConstructor(
- new Class[] { targetServiceClass },
- null,
- "{ super(); _targetService = $1; }");
+ cf.addConstructor(new Class[]
+ { targetServiceClass }, null, "{ super(); _targetService = $1; }");
BodyBuilder b = new BodyBuilder();
b.begin();
- b.addln(
- "{0} property = _targetService.{1}();",
- serviceInterface.getName(),
- readPropertyMethodName);
+ b.addln("{0} property = _targetService.{1}();",
serviceInterface.getName(), readPropertyMethodName);
b.addln("if (property == null)");
b.add(" throw new java.lang.NullPointerException(");
@@ -137,17 +112,12 @@
b.end();
- MethodSignature sig =
- new MethodSignature(serviceInterface, "_targetServiceProperty",
null, null);
+ MethodSignature sig = new MethodSignature(serviceInterface,
"_targetServiceProperty", null, null);
cf.addMethod(Modifier.FINAL | Modifier.PRIVATE, sig, b.toString());
}
- private void addMethods(
- ClassFab cf,
- String serviceId,
- Class serviceInterface,
- String propertyName,
- Object targetService)
+ private void addMethods(ClassFab cf, String serviceId, Class
serviceInterface, String propertyName,
+ Object targetService)
{
boolean toString = false;
@@ -165,17 +135,12 @@
}
if (!toString)
- ClassFabUtils.addToStringMethod(
- cf,
- ImplMessages.servicePropertyToString(
- serviceId,
- serviceInterface,
- propertyName,
- targetService));
+ ClassFabUtils.addToStringMethod(cf,
ImplMessages.servicePropertyToString(serviceId, serviceInterface,
+ propertyName, targetService));
}
public void setClassFactory(ClassFactory factory)
{
_classFactory = factory;
}
-}
+}
\ No newline at end of file
No revision
No revision
1.8.2.3 +38 -51
jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/LoggingInterceptorFactory.java
Index: LoggingInterceptorFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/impl/LoggingInterceptorFactory.java,v
retrieving revision 1.8.2.2
retrieving revision 1.8.2.3
diff -u -r1.8.2.2 -r1.8.2.3
--- LoggingInterceptorFactory.java 8 Sep 2004 17:18:09 -0000 1.8.2.2
+++ LoggingInterceptorFactory.java 14 Sep 2004 17:48:26 -0000 1.8.2.3
@@ -35,23 +35,22 @@
import org.apache.hivemind.service.MethodSignature;
/**
- * An interceptor factory that adds logging capability to a service.
- * The logging is based upon the Jakarta
- * <a
href="http://jakarta.apache.org/commons/logging.html">commons-logging</a>
toolkit,
- * which makes
- * it very transportable.
- *
+ * An interceptor factory that adds logging capability to a service. The
logging
+ * is based upon the Jakarta <a
+ * href="http://jakarta.apache.org/commons/logging.html">commons-logging </a>
+ * toolkit, which makes it very transportable.
* <p>
- * The interceptor will log entry to each method and exit from the method
- * (with return value), plus log any exceptions thrown by the method.
- * The logger used is the <em>id of the service</em>, which is not
necessarily
- * the name of the implementing class. Logging occurs at the debug level.
- *
+ * The interceptor will log entry to each method and exit from the method
(with
+ * return value), plus log any exceptions thrown by the method. The logger
used
+ * is the <em>id of the service</em>, which is not necessarily the name of
+ * the implementing class. Logging occurs at the debug level.
+ *
* @author Howard Lewis Ship
*/
public class LoggingInterceptorFactory implements ServiceInterceptorFactory
{
private ClassFactory _factory;
+
private String _serviceId;
/**
@@ -166,18 +165,13 @@
}
/**
- * Creates a toString() method that identify the interceptor service id,
- * the intercepted service id, and the service interface class name).
+ * Creates a toString() method that identify the interceptor service id,
the
+ * intercepted service id, and the service interface class name).
*/
protected void addToStringMethod(InterceptorStack stack, ClassFab fab)
{
- ClassFabUtils.addToStringMethod(
- fab,
- "<LoggingInterceptor for "
- + stack.getServiceExtensionPointId()
- + "("
- + stack.getServiceInterface().getName()
- + ")>");
+ ClassFabUtils.addToStringMethod(fab, "<LoggingInterceptor for " +
stack.getServiceExtensionPointId() + "("
+ + stack.getServiceInterface().getName() + ")>");
}
@@ -206,8 +200,7 @@
String name = ClassFabUtils.generateClassName("Interceptor");
- ClassFab classFab =
- _factory.newClass(name, Object.class,
module.getClassResolver().getClassLoader());
+ ClassFab classFab = _factory.newClass(name, Object.class,
module.getClassResolver().getClassLoader());
classFab.addInterface(serviceInterfaceClass);
@@ -220,35 +213,34 @@
private void createInfrastructure(InterceptorStack stack, ClassFab
classFab)
{
- Class topClass = stack.peek().getClass();
+ Class topClass = ClassFabUtils.getInstanceClass(stack.peek(),
stack.getServiceInterface());
classFab.addField("_log", Log.class);
- // This is very important: since we know the instance of the top
object (the next
- // object in the pipeline for this service), we can build the
instance variable
- // and constructor to use the exact class rather than the service
interface.
- // That's more efficient at runtime, lowering the cost of using
interceptors.
+ // This is very important: since we know the instance of the top
object
+ // (the next
+ // object in the pipeline for this service), we can build the
instance
+ // variable
+ // and constructor to use the exact class rather than the service
+ // interface.
+ // That's more efficient at runtime, lowering the cost of using
+ // interceptors.
// One of the reasons I prefer Javassist over JDK Proxies.
classFab.addField("_inner", topClass);
- classFab.addConstructor(
- new Class[] { Log.class, topClass },
- null,
- "{ _log = $1; _inner = $2; }");
+ classFab.addConstructor(new Class[]
+ { Log.class, topClass }, null, "{ _log = $1; _inner = $2; }");
}
/**
- * Creates the interceptor.
- * The class that is created is cached; if an interceptor is requested
- * for the same extension point, then the previously constructed class
- * is reused (this can happen with the threaded service model, for
example,
- * when a thread-local service implementation is created for different
threads).
+ * Creates the interceptor. The class that is created is cached; if an
+ * interceptor is requested for the same extension point, then the
+ * previously constructed class is reused (this can happen with the
threaded
+ * service model, for example, when a thread-local service
implementation is
+ * created for different threads).
*/
- public void createInterceptor(
- InterceptorStack stack,
- Module contributingModule,
- List parameters)
+ public void createInterceptor(InterceptorStack stack, Module
contributingModule, List parameters)
{
Class interceptorClass = constructInterceptorClass(stack,
parameters);
@@ -260,13 +252,8 @@
}
catch (Exception ex)
{
- throw new ApplicationRuntimeException(
- ServiceMessages.errorInstantiatingInterceptor(
- _serviceId,
- stack,
- interceptorClass,
- ex),
- ex);
+ throw new
ApplicationRuntimeException(ServiceMessages.errorInstantiatingInterceptor(_serviceId,
stack,
+ interceptorClass, ex), ex);
}
}
@@ -280,14 +267,14 @@
return mc == null || mc.getInclude();
}
- private Object instantiateInterceptor(InterceptorStack stack, Class
interceptorClass)
- throws Exception
+ private Object instantiateInterceptor(InterceptorStack stack, Class
interceptorClass) throws Exception
{
Object stackTop = stack.peek();
Constructor c = interceptorClass.getConstructors()[0];
- return c.newInstance(new Object[] { stack.getServiceLog(), stackTop
});
+ return c.newInstance(new Object[]
+ { stack.getServiceLog(), stackTop });
}
public void setFactory(ClassFactory factory)
@@ -299,4 +286,4 @@
{
_serviceId = string;
}
-}
+}
\ No newline at end of file
No revision
No revision
1.3.2.1 +37 -18
jakarta-hivemind/framework/src/java/org/apache/hivemind/service/ClassFabUtils.java
Index: ClassFabUtils.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/service/ClassFabUtils.java,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -r1.3 -r1.3.2.1
--- ClassFabUtils.java 12 Jun 2004 18:43:41 -0000 1.3
+++ ClassFabUtils.java 14 Sep 2004 17:48:26 -0000 1.3.2.1
@@ -16,10 +16,11 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
/**
* Static class containing utility methods.
- *
+ *
* @author Howard Lewis Ship
*/
public class ClassFabUtils
@@ -33,8 +34,7 @@
}
/**
- * Generates a unique class name, which will be in the
- * default package.
+ * Generates a unique class name, which will be in the default package.
*/
public static synchronized String generateClassName(String baseName)
@@ -43,11 +43,10 @@
}
/**
- * Javassist needs the class name to be as it appears in source code,
even for arrays.
- * Invoking getName() on a Class instance representing an array returns
the internal
- * format (i.e, "[...;" or something). This returns it as it would
appear in
- * Java code.
- *
+ * Javassist needs the class name to be as it appears in source code,
even
+ * for arrays. Invoking getName() on a Class instance representing an
array
+ * returns the internal format (i.e, "[...;" or something). This returns
it
+ * as it would appear in Java code.
*/
public static String getJavaClassName(Class inputClass)
{
@@ -58,9 +57,9 @@
}
/**
- * Returns true if the method is the standard toString() method.
- * Very few interfaces will ever include this method as part of
- * the interface, but we have to be sure.
+ * Returns true if the method is the standard toString() method. Very few
+ * interfaces will ever include this method as part of the interface,
but we
+ * have to be sure.
*/
public static boolean isToString(Method method)
{
@@ -77,8 +76,10 @@
* Adds a <code>toString()</code> method to a class that returns a fixed,
* pre-computed value.
*
- * @param classFab ClassFab used to construct the new class.
- * @param toStringResult fixed result to be returned by the method.
+ * @param classFab
+ * ClassFab used to construct the new class.
+ * @param toStringResult
+ * fixed result to be returned by the method.
*/
public static void addToStringMethod(ClassFab classFab, String
toStringResult)
{
@@ -88,10 +89,28 @@
buffer.append(QUOTE);
buffer.append(";");
- classFab.addMethod(
- Modifier.PUBLIC,
- new MethodSignature(String.class, "toString", null, null),
- buffer.toString());
+ classFab.addMethod(Modifier.PUBLIC, new
MethodSignature(String.class, "toString", null, null), buffer
+ .toString());
}
-}
+ /**
+ * Returns the class of an instance. However, if the instance is, in
fact, a
+ * JDK proxy, returns the interfaceClass (because JDK proxies do not work
+ * with Javassist).
+ *
+ * @param instance
+ * the object instance to obtain a class from
+ * @param interfaceClass
+ * the interface class to return if the instance is a JDK
proxy.
+ */
+ public static Class getInstanceClass(Object instance, Class
interfaceClass)
+ {
+ Class instanceClass = instance.getClass();
+
+ if (Proxy.isProxyClass(instanceClass))
+ return interfaceClass;
+
+ return instanceClass;
+ }
+
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]