You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/03/19 01:10:39 UTC
svn commit: r519755 - in
/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc:
internal/ internal/services/ services/
Author: hlship
Date: Sun Mar 18 17:10:38 2007
New Revision: 519755
URL: http://svn.apache.org/viewvc?view=rev&rev=519755
Log:
Add ability to define ClasFab fields with modifiers (such as final) and change several generated proxy classes to use final fields for injected, immutable values.
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BridgeBuilder.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFabImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceLifecycle.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFab.java
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/ModuleImpl.java Sun Mar 18 17:10:38 2007
@@ -366,7 +366,7 @@
{
ClassFab cf = _registry.newClass(serviceInterface);
- cf.addField("_creator", ObjectCreator.class);
+ cf.addField("_creator", Modifier.PRIVATE | Modifier.FINAL, ObjectCreator.class);
cf.addConstructor(new Class[]
{ ObjectCreator.class }, null, "_creator = $1;");
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BridgeBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BridgeBuilder.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BridgeBuilder.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/BridgeBuilder.java Sun Mar 18 17:10:38 2007
@@ -108,8 +108,8 @@
private void createInfrastructure()
{
- _classFab.addField("_next", _serviceInterface);
- _classFab.addField("_filter", _filterInterface);
+ _classFab.addField("_next", Modifier.PRIVATE | Modifier.FINAL, _serviceInterface);
+ _classFab.addField("_filter", Modifier.PRIVATE | Modifier.FINAL, _filterInterface);
_classFab.addConstructor(new Class[]
{ _serviceInterface, _filterInterface }, null, "{ _next = $1; _filter = $2; }");
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ChainBuilderImpl.java Sun Mar 18 17:10:38 2007
@@ -12,205 +12,199 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.internal.services;
-
-import static java.lang.String.format;
+package org.apache.tapestry.ioc.internal.services;
+
+import static java.lang.String.format;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newConcurrentMap;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.tapestry.ioc.services.ChainBuilder;
-import org.apache.tapestry.ioc.services.ClassFab;
-import org.apache.tapestry.ioc.services.ClassFabUtils;
-import org.apache.tapestry.ioc.services.ClassFactory;
-import org.apache.tapestry.ioc.services.MethodIterator;
-import org.apache.tapestry.ioc.services.MethodSignature;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry.ioc.services.ChainBuilder;
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFabUtils;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.MethodIterator;
+import org.apache.tapestry.ioc.services.MethodSignature;
import org.apache.tapestry.ioc.util.BodyBuilder;
-
-/**
- *
- */
-public class ChainBuilderImpl implements ChainBuilder
-{
- private final ClassFactory _classFactory;
-
- /**
- * Map, keyed on service interface, of implementation Class.
- */
-
- private Map<Class, Class> _cache = newConcurrentMap();
-
- public ChainBuilderImpl(ClassFactory classFactory)
- {
- _classFactory = classFactory;
- }
-
- @SuppressWarnings("unchecked")
- public <T> T build(Class<T> commandInterface, List<T> commands)
- {
- Class<T> chainClass = findImplementationClass(commandInterface);
-
- return createInstance(chainClass, commands);
- }
-
- private Class findImplementationClass(Class commandInterface)
- {
- Class result = _cache.get(commandInterface);
-
- if (result == null)
- {
- result = constructImplementationClass(commandInterface);
- _cache.put(commandInterface, result);
- }
-
- return result;
- }
-
- private Class constructImplementationClass(Class commandInterface)
- {
- // In rare, rare cases, a race condition to create an implementation class
- // for the same interface may occur. We just let that happen, and there'll
- // be two different classes corresponding to the same interface.
-
- String name = ClassFabUtils.generateClassName(commandInterface);
-
- ClassFab cf = _classFactory.newClass(name, Object.class);
-
- addInfrastructure(cf, commandInterface);
-
- addMethods(cf, commandInterface);
-
- return cf.createClass();
- }
-
- private void addInfrastructure(ClassFab cf, Class commandInterface)
- {
- // Array types are very, very tricky to deal with.
- // Also, generics don't help (<T> new T[]) is still java.lang.Object[].
-
- String arrayClassName = commandInterface.getCanonicalName() + "[]";
- String jvmName = ClassFabUtils.toJVMBinaryName(arrayClassName);
-
- Class array = null;
-
- try
- {
- ClassLoader loader = commandInterface.getClass().getClassLoader();
- if (loader == null)
- loader = Thread.currentThread().getContextClassLoader();
-
- array = Class.forName(jvmName, true, loader);
- }
- catch (Exception ex)
- {
- throw new RuntimeException(ex);
- }
-
- cf.addInterface(commandInterface);
- cf.addField("_commands", array);
-
- BodyBuilder builder = new BodyBuilder();
- builder.addln("_commands = (%s[]) $1.toArray(new %<s[0]);", commandInterface.getName());
-
- cf.addConstructor(new Class[]
- { List.class }, null, builder.toString());
- }
-
+
+public class ChainBuilderImpl implements ChainBuilder
+{
+ private final ClassFactory _classFactory;
+
+ /**
+ * Map, keyed on service interface, of implementation Class.
+ */
+
+ private Map<Class, Class> _cache = newConcurrentMap();
+
+ public ChainBuilderImpl(ClassFactory classFactory)
+ {
+ _classFactory = classFactory;
+ }
+
@SuppressWarnings("unchecked")
- private <T> T createInstance(Class<T> instanceClass, List<T> commands)
- {
- try
- {
- Constructor<T> ctor = instanceClass.getConstructors()[0];
-
- return instanceClass.cast(ctor.newInstance(commands));
- }
- catch (Exception ex)
- {
- // This should not be reachable!
- throw new RuntimeException(ex);
- }
-
- }
-
- private void addMethods(ClassFab cf, Class commandInterface)
- {
- MethodIterator mi = new MethodIterator(commandInterface);
-
- while (mi.hasNext())
- {
- MethodSignature sig = mi.next();
-
- addMethod(cf, commandInterface, sig);
- }
-
- if (!mi.getToString())
- cf.addToString(format("<Command chain of %s>", commandInterface.getName()));
- }
-
- private void addMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
- {
- Class returnType = sig.getReturnType();
-
- if (returnType.equals(void.class))
- {
- addVoidMethod(cf, commandInterface, sig);
- return;
- }
-
- String defaultValue = defaultForReturnType(returnType);
-
- BodyBuilder builder = new BodyBuilder();
- builder.begin();
-
- builder.addln("%s result = %s;", ClassFabUtils.toJavaClassName(returnType), defaultValue);
- builder.addln("for (int i = 0; i < _commands.length; i++)");
-
- builder.begin();
- builder.addln("result = _commands[i].%s($$);", sig.getName());
-
- builder.addln("if (result != %s) break;", defaultValue);
-
- builder.end();
-
- builder.addln("return result;");
- builder.end();
-
- cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
- }
-
- private String defaultForReturnType(Class returnType)
- {
- // For all object and array types.
-
- if (!returnType.isPrimitive())
- return "null";
-
- if (returnType.equals(boolean.class))
- return "false";
-
- // Assume, then, that it is a numeric type (this method
- // isn't called for type void). Javassist seems to be
- // able to handle 0 for all numeric types.
-
- return "0";
- }
-
- private void addVoidMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
- {
- BodyBuilder builder = new BodyBuilder();
-
- builder.begin();
-
- builder.addln("for (int i = 0; i < _commands.length; i++)");
- builder.addln(" _commands[i].%s($$);", sig.getName());
-
- builder.end();
-
- cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
- }
-
-}
+ public <T> T build(Class<T> commandInterface, List<T> commands)
+ {
+ Class<T> chainClass = findImplementationClass(commandInterface);
+
+ return createInstance(chainClass, commands);
+ }
+
+ private Class findImplementationClass(Class commandInterface)
+ {
+ Class result = _cache.get(commandInterface);
+
+ if (result == null)
+ {
+ result = constructImplementationClass(commandInterface);
+ _cache.put(commandInterface, result);
+ }
+
+ return result;
+ }
+
+ private Class constructImplementationClass(Class commandInterface)
+ {
+ // In rare, rare cases, a race condition to create an implementation class
+ // for the same interface may occur. We just let that happen, and there'll
+ // be two different classes corresponding to the same interface.
+
+ String name = ClassFabUtils.generateClassName(commandInterface);
+
+ ClassFab cf = _classFactory.newClass(name, Object.class);
+
+ addInfrastructure(cf, commandInterface);
+
+ addMethods(cf, commandInterface);
+
+ return cf.createClass();
+ }
+
+ private void addInfrastructure(ClassFab cf, Class commandInterface)
+ {
+ // Array types are very, very tricky to deal with.
+ // Also, generics don't help (<T> new T[]) is still java.lang.Object[].
+
+ String arrayClassName = commandInterface.getCanonicalName() + "[]";
+ String jvmName = ClassFabUtils.toJVMBinaryName(arrayClassName);
+
+ Class array = null;
+
+ try
+ {
+ ClassLoader loader = commandInterface.getClass().getClassLoader();
+ if (loader == null) loader = Thread.currentThread().getContextClassLoader();
+
+ array = Class.forName(jvmName, true, loader);
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+
+ cf.addInterface(commandInterface);
+ cf.addField("_commands", Modifier.PRIVATE | Modifier.FINAL, array);
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.addln("_commands = (%s[]) $1.toArray(new %<s[0]);", commandInterface.getName());
+
+ cf.addConstructor(new Class[]
+ { List.class }, null, builder.toString());
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T createInstance(Class<T> instanceClass, List<T> commands)
+ {
+ try
+ {
+ Constructor<T> ctor = instanceClass.getConstructors()[0];
+
+ return instanceClass.cast(ctor.newInstance(commands));
+ }
+ catch (Exception ex)
+ {
+ // This should not be reachable!
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+ private void addMethods(ClassFab cf, Class commandInterface)
+ {
+ MethodIterator mi = new MethodIterator(commandInterface);
+
+ while (mi.hasNext())
+ {
+ MethodSignature sig = mi.next();
+
+ addMethod(cf, commandInterface, sig);
+ }
+
+ if (!mi.getToString())
+ cf.addToString(format("<Command chain of %s>", commandInterface.getName()));
+ }
+
+ private void addMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
+ {
+ Class returnType = sig.getReturnType();
+
+ if (returnType.equals(void.class))
+ {
+ addVoidMethod(cf, commandInterface, sig);
+ return;
+ }
+
+ String defaultValue = defaultForReturnType(returnType);
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ builder.addln("%s result = %s;", ClassFabUtils.toJavaClassName(returnType), defaultValue);
+ builder.addln("for (int i = 0; i < _commands.length; i++)");
+
+ builder.begin();
+ builder.addln("result = _commands[i].%s($$);", sig.getName());
+
+ builder.addln("if (result != %s) break;", defaultValue);
+
+ builder.end();
+
+ builder.addln("return result;");
+ builder.end();
+
+ cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
+ }
+
+ private String defaultForReturnType(Class returnType)
+ {
+ // For all object and array types.
+
+ if (!returnType.isPrimitive()) return "null";
+
+ if (returnType.equals(boolean.class)) return "false";
+
+ // Assume, then, that it is a numeric type (this method
+ // isn't called for type void). Javassist seems to be
+ // able to handle 0 for all numeric types.
+
+ return "0";
+ }
+
+ private void addVoidMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
+ {
+ BodyBuilder builder = new BodyBuilder();
+
+ builder.begin();
+
+ builder.addln("for (int i = 0; i < _commands.length; i++)");
+ builder.addln(" _commands[i].%s($$);", sig.getName());
+
+ builder.end();
+
+ cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFabImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFabImpl.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFabImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFabImpl.java Sun Mar 18 17:10:38 2007
@@ -137,6 +137,11 @@
public void addField(String name, Class type)
{
+ addField(name, Modifier.PRIVATE, type);
+ }
+
+ public void addField(String name, int modifiers, Class type)
+ {
_lock.check();
CtClass ctType = convertClass(type);
@@ -144,7 +149,7 @@
try
{
CtField field = new CtField(ctType, name, getCtClass());
- field.setModifiers(Modifier.PRIVATE);
+ field.setModifiers(modifiers);
getCtClass().addField(field);
}
@@ -154,7 +159,8 @@
throw new RuntimeException(ServiceMessages.unableToAddField(name, getCtClass(), ex), ex);
}
- _formatter.format("private %s %s;\n\n", ClassFabUtils.toJavaClassName(type), name);
+ _formatter.format("%s %s %s;\n\n", Modifier.toString(modifiers), ClassFabUtils
+ .toJavaClassName(type), name);
}
public void proxyMethodsToDelegate(Class serviceInterface, String delegateExpression,
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/LoggingDecoratorImpl.java Sun Mar 18 17:10:38 2007
@@ -12,156 +12,151 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.internal.services;
-
-import static java.lang.String.format;
-import static org.apache.tapestry.ioc.services.ClassFabUtils.toJavaClassName;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-
-import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.services.ClassFab;
-import org.apache.tapestry.ioc.services.ClassFactory;
-import org.apache.tapestry.ioc.services.ExceptionTracker;
-import org.apache.tapestry.ioc.services.LoggingDecorator;
-import org.apache.tapestry.ioc.services.MethodIterator;
-import org.apache.tapestry.ioc.services.MethodSignature;
+package org.apache.tapestry.ioc.internal.services;
+
+import static java.lang.String.format;
+import static org.apache.tapestry.ioc.services.ClassFabUtils.toJavaClassName;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.ExceptionTracker;
+import org.apache.tapestry.ioc.services.LoggingDecorator;
+import org.apache.tapestry.ioc.services.MethodIterator;
+import org.apache.tapestry.ioc.services.MethodSignature;
import org.apache.tapestry.ioc.util.BodyBuilder;
-
-/**
- *
- */
-public class LoggingDecoratorImpl implements LoggingDecorator
-{
- private final ClassFactory _classFactory;
-
- private final ExceptionTracker _exceptionTracker;
-
- public LoggingDecoratorImpl(ClassFactory classFactory, ExceptionTracker exceptionTracker)
- {
- _classFactory = classFactory;
- _exceptionTracker = exceptionTracker;
- }
-
- public <T> T build(Class<T> serviceInterface, T delegate, String serviceId, Log serviceLog)
- {
- Class interceptorClass = createInterceptorClass(serviceInterface, serviceId);
-
- ServiceLogger logger = new ServiceLogger(serviceLog, _exceptionTracker);
-
- Constructor cc = interceptorClass.getConstructors()[0];
-
- Object interceptor = null;
- Throwable fail = null;
-
- try
- {
- interceptor = cc.newInstance(delegate, logger);
- }
- catch (InvocationTargetException ite)
- {
- fail = ite.getTargetException();
- }
- catch (Exception ex)
- {
- fail = ex;
- }
-
- if (fail != null)
- throw new RuntimeException(fail);
-
- return serviceInterface.cast(interceptor);
- }
-
- private Class createInterceptorClass(Class serviceInterface, String serviceId)
- {
- ClassFab cf = _classFactory.newClass(serviceInterface);
-
- cf.addField("_delegate", serviceInterface);
- cf.addField("_logger", ServiceLogger.class);
-
- cf.addConstructor(new Class[]
- { serviceInterface, ServiceLogger.class }, null, "{ _delegate = $1; _logger = $2; }");
-
- addMethods(cf, serviceInterface, serviceId);
-
- return cf.createClass();
- }
-
- private void addMethods(ClassFab cf, Class serviceInterface, String serviceId)
- {
- MethodIterator mi = new MethodIterator(serviceInterface);
-
- while (mi.hasNext())
- addMethod(cf, mi.next());
-
- if (!mi.getToString())
- cf.addToString(ServiceMessages.loggingInterceptor(serviceId, serviceInterface));
- }
-
- private void addMethod(ClassFab cf, MethodSignature signature)
- {
- String name = '"' + signature.getName() + '"';
- Class returnType = signature.getReturnType();
- boolean isVoid = returnType.equals(void.class);
-
- // We'll see how well Javassist handles void methods with this setup
-
- BodyBuilder builder = new BodyBuilder();
- builder.begin();
- builder.addln("boolean debug = _logger.isDebugEnabled();");
-
- builder.addln("if (debug)");
- builder.addln(" _logger.entry(%s, $args);", name);
-
- builder.addln("try");
- builder.begin();
-
- if (!isVoid)
- builder.add("%s result = ", toJavaClassName(returnType));
-
- builder.addln("_delegate.%s($$);", signature.getName());
-
- if (isVoid)
- {
- builder.addln("if (debug)");
- builder.addln(format(" _logger.voidExit(%s);", name));
- builder.addln("return;");
- }
- else
- {
- builder.addln("if (debug)");
- builder.addln(format(" _logger.exit(%s, ($w)result);", name));
- builder.addln("return result;");
- }
-
- builder.end(); // try
-
- // Now, a catch for each declared exception (if any)
-
- if (signature.getExceptionTypes() != null)
- for (Class exceptionType : signature.getExceptionTypes())
- addExceptionHandler(builder, name, exceptionType);
-
- // And a catch for RuntimeException
-
- addExceptionHandler(builder, name, RuntimeException.class);
-
- builder.end();
-
- cf.addMethod(Modifier.PUBLIC, signature, builder.toString());
- }
-
- private void addExceptionHandler(BodyBuilder builder, String quotedMethodName,
- Class exceptionType)
- {
- builder.addln("catch (%s ex)", exceptionType.getName());
- builder.begin();
- builder.addln("if (debug)");
- builder.addln(" _logger.fail(%s, ex);", quotedMethodName);
- builder.addln("throw ex;");
- builder.end();
- }
-}
+
+public class LoggingDecoratorImpl implements LoggingDecorator
+{
+ private final ClassFactory _classFactory;
+
+ private final ExceptionTracker _exceptionTracker;
+
+ public LoggingDecoratorImpl(ClassFactory classFactory, ExceptionTracker exceptionTracker)
+ {
+ _classFactory = classFactory;
+ _exceptionTracker = exceptionTracker;
+ }
+
+ public <T> T build(Class<T> serviceInterface, T delegate, String serviceId, Log serviceLog)
+ {
+ Class interceptorClass = createInterceptorClass(serviceInterface, serviceId);
+
+ ServiceLogger logger = new ServiceLogger(serviceLog, _exceptionTracker);
+
+ Constructor cc = interceptorClass.getConstructors()[0];
+
+ Object interceptor = null;
+ Throwable fail = null;
+
+ try
+ {
+ interceptor = cc.newInstance(delegate, logger);
+ }
+ catch (InvocationTargetException ite)
+ {
+ fail = ite.getTargetException();
+ }
+ catch (Exception ex)
+ {
+ fail = ex;
+ }
+
+ if (fail != null) throw new RuntimeException(fail);
+
+ return serviceInterface.cast(interceptor);
+ }
+
+ private Class createInterceptorClass(Class serviceInterface, String serviceId)
+ {
+ ClassFab cf = _classFactory.newClass(serviceInterface);
+
+ cf.addField("_delegate", Modifier.PRIVATE | Modifier.FINAL, serviceInterface);
+ cf.addField("_logger", Modifier.PRIVATE | Modifier.FINAL, ServiceLogger.class);
+
+ cf.addConstructor(new Class[]
+ { serviceInterface, ServiceLogger.class }, null, "{ _delegate = $1; _logger = $2; }");
+
+ addMethods(cf, serviceInterface, serviceId);
+
+ return cf.createClass();
+ }
+
+ private void addMethods(ClassFab cf, Class serviceInterface, String serviceId)
+ {
+ MethodIterator mi = new MethodIterator(serviceInterface);
+
+ while (mi.hasNext())
+ addMethod(cf, mi.next());
+
+ if (!mi.getToString())
+ cf.addToString(ServiceMessages.loggingInterceptor(serviceId, serviceInterface));
+ }
+
+ private void addMethod(ClassFab cf, MethodSignature signature)
+ {
+ String name = '"' + signature.getName() + '"';
+ Class returnType = signature.getReturnType();
+ boolean isVoid = returnType.equals(void.class);
+
+ // We'll see how well Javassist handles void methods with this setup
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+ builder.addln("boolean debug = _logger.isDebugEnabled();");
+
+ builder.addln("if (debug)");
+ builder.addln(" _logger.entry(%s, $args);", name);
+
+ builder.addln("try");
+ builder.begin();
+
+ if (!isVoid) builder.add("%s result = ", toJavaClassName(returnType));
+
+ builder.addln("_delegate.%s($$);", signature.getName());
+
+ if (isVoid)
+ {
+ builder.addln("if (debug)");
+ builder.addln(format(" _logger.voidExit(%s);", name));
+ builder.addln("return;");
+ }
+ else
+ {
+ builder.addln("if (debug)");
+ builder.addln(format(" _logger.exit(%s, ($w)result);", name));
+ builder.addln("return result;");
+ }
+
+ builder.end(); // try
+
+ // Now, a catch for each declared exception (if any)
+
+ if (signature.getExceptionTypes() != null)
+ for (Class exceptionType : signature.getExceptionTypes())
+ addExceptionHandler(builder, name, exceptionType);
+
+ // And a catch for RuntimeException
+
+ addExceptionHandler(builder, name, RuntimeException.class);
+
+ builder.end();
+
+ cf.addMethod(Modifier.PUBLIC, signature, builder.toString());
+ }
+
+ private void addExceptionHandler(BodyBuilder builder, String quotedMethodName,
+ Class exceptionType)
+ {
+ builder.addln("catch (%s ex)", exceptionType.getName());
+ builder.begin();
+ builder.addln("if (debug)");
+ builder.addln(" _logger.fail(%s, ex);", quotedMethodName);
+ builder.addln("throw ex;");
+ builder.end();
+ }
+}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceLifecycle.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceLifecycle.java Sun Mar 18 17:10:38 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -12,98 +12,96 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.internal.services;
-
-import static java.lang.String.format;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-
-import org.apache.tapestry.ioc.ObjectCreator;
-import org.apache.tapestry.ioc.ServiceLifecycle;
-import org.apache.tapestry.ioc.ServiceResources;
-import org.apache.tapestry.ioc.services.ClassFab;
-import org.apache.tapestry.ioc.services.ClassFactory;
-import org.apache.tapestry.ioc.services.MethodSignature;
-import org.apache.tapestry.ioc.services.ThreadCleanupHub;
-
-/**
- * Allows a service to exist "per thread" (in each thread). This involves an inner proxy, with a
- * ThreadLocal whose initial value is derived from a {@link org.apache.tapestry.ioc.ObjectCreator}.
- * Method invocations are delegated to the per-thread service instance. The proxy also implements
- * {@link org.apache.tapestry.ioc.services.ThreadCleanupListener} so that it can discard the
- * per-thread implementation.
- * <p>
- * This scheme ensures that, although the service builder method will be invoked many times over the
- * life of the application, the service decoration process occurs only once. The final calling chain
- * is: Service Proxy --> Decorator(s) --> PerThread Proxy --> (per thread) instance.
- *
- *
- */
-public class PerThreadServiceLifecycle implements ServiceLifecycle
-{
- private final ThreadCleanupHub _threadCleanupHub;
-
- private final ClassFactory _classFactory;
-
- private static final String PER_THREAD_METHOD_NAME = "_perThreadInstance";
-
- public PerThreadServiceLifecycle(ThreadCleanupHub threadCleanupHub, ClassFactory classFactory)
- {
- _threadCleanupHub = threadCleanupHub;
- _classFactory = classFactory;
- }
-
- public Object createService(ServiceResources resources, final ObjectCreator creator)
- {
- Class proxyClass = createProxyClass(resources);
-
- ObjectCreator perThreadCreator = new PerThreadServiceCreator(_threadCleanupHub, creator);
-
- try
- {
- Constructor ctor = proxyClass.getConstructors()[0];
-
- return ctor.newInstance(perThreadCreator);
- }
- catch (InvocationTargetException ex)
- {
- throw new RuntimeException(ex.getCause());
- }
- catch (Exception ex)
- {
- throw new RuntimeException(ex);
- }
- }
-
- private Class createProxyClass(ServiceResources resources)
- {
- Class serviceInterface = resources.getServiceInterface();
-
- ClassFab cf = _classFactory.newClass(serviceInterface);
-
- cf.addField("_creator", ObjectCreator.class);
-
- // Constructor takes a ServiceCreator
-
- cf.addConstructor(new Class[]
- { ObjectCreator.class }, null, "_creator = $1;");
-
- String body = format("return (%s) _creator.createObject();", serviceInterface.getName());
-
- MethodSignature sig = new MethodSignature(serviceInterface, PER_THREAD_METHOD_NAME, null,
- null);
-
- cf.addMethod(Modifier.PRIVATE, sig, body);
-
- String toString = format(
- "<PerThread Proxy for %s(%s)>",
- resources.getServiceId(),
- serviceInterface.getName());
-
- cf.proxyMethodsToDelegate(serviceInterface, PER_THREAD_METHOD_NAME + "()", toString);
-
- return cf.createClass();
- }
-}
+package org.apache.tapestry.ioc.internal.services;
+
+import static java.lang.String.format;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceLifecycle;
+import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.MethodSignature;
+import org.apache.tapestry.ioc.services.ThreadCleanupHub;
+
+/**
+ * Allows a service to exist "per thread" (in each thread). This involves an inner proxy, with a
+ * ThreadLocal whose initial value is derived from a {@link org.apache.tapestry.ioc.ObjectCreator}.
+ * Method invocations are delegated to the per-thread service instance. The proxy also implements
+ * {@link org.apache.tapestry.ioc.services.ThreadCleanupListener} so that it can discard the
+ * per-thread implementation.
+ * <p>
+ * This scheme ensures that, although the service builder method will be invoked many times over the
+ * life of the application, the service decoration process occurs only once. The final calling chain
+ * is: Service Proxy --> Decorator(s) --> PerThread Proxy --> (per thread) instance.
+ */
+public class PerThreadServiceLifecycle implements ServiceLifecycle
+{
+ private final ThreadCleanupHub _threadCleanupHub;
+
+ private final ClassFactory _classFactory;
+
+ private static final String PER_THREAD_METHOD_NAME = "_perThreadInstance";
+
+ public PerThreadServiceLifecycle(ThreadCleanupHub threadCleanupHub, ClassFactory classFactory)
+ {
+ _threadCleanupHub = threadCleanupHub;
+ _classFactory = classFactory;
+ }
+
+ public Object createService(ServiceResources resources, final ObjectCreator creator)
+ {
+ Class proxyClass = createProxyClass(resources);
+
+ ObjectCreator perThreadCreator = new PerThreadServiceCreator(_threadCleanupHub, creator);
+
+ try
+ {
+ Constructor ctor = proxyClass.getConstructors()[0];
+
+ return ctor.newInstance(perThreadCreator);
+ }
+ catch (InvocationTargetException ex)
+ {
+ throw new RuntimeException(ex.getCause());
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private Class createProxyClass(ServiceResources resources)
+ {
+ Class serviceInterface = resources.getServiceInterface();
+
+ ClassFab cf = _classFactory.newClass(serviceInterface);
+
+ cf.addField("_creator", Modifier.PRIVATE | Modifier.FINAL, ObjectCreator.class);
+
+ // Constructor takes a ServiceCreator
+
+ cf.addConstructor(new Class[]
+ { ObjectCreator.class }, null, "_creator = $1;");
+
+ String body = format("return (%s) _creator.createObject();", serviceInterface.getName());
+
+ MethodSignature sig = new MethodSignature(serviceInterface, PER_THREAD_METHOD_NAME, null,
+ null);
+
+ cf.addMethod(Modifier.PRIVATE, sig, body);
+
+ String toString = format(
+ "<PerThread Proxy for %s(%s)>",
+ resources.getServiceId(),
+ serviceInterface.getName());
+
+ cf.proxyMethodsToDelegate(serviceInterface, PER_THREAD_METHOD_NAME + "()", toString);
+
+ return cf.createClass();
+ }
+}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/PropertyShadowBuilderImpl.java Sun Mar 18 17:10:38 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -12,88 +12,85 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.internal.services;
-
-import static java.lang.String.format;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-
-import org.apache.tapestry.ioc.services.ClassFab;
-import org.apache.tapestry.ioc.services.ClassFactory;
-import org.apache.tapestry.ioc.services.MethodSignature;
-import org.apache.tapestry.ioc.services.PropertyAccess;
-import org.apache.tapestry.ioc.services.PropertyAdapter;
-import org.apache.tapestry.ioc.services.PropertyShadowBuilder;
-
-/**
- *
- */
-public class PropertyShadowBuilderImpl implements PropertyShadowBuilder
-{
- private final ClassFactory _classFactory;
-
- private final PropertyAccess _propertyAccess;
-
- public PropertyShadowBuilderImpl(ClassFactory classFactory, PropertyAccess propertyAccess)
- {
- _classFactory = classFactory;
- _propertyAccess = propertyAccess;
- }
-
- public <T> T build(Object source, String propertyName, Class<T> propertyType)
- {
- Class sourceClass = source.getClass();
- PropertyAdapter adapter = _propertyAccess.getAdapter(sourceClass).getPropertyAdapter(
- propertyName);
-
- // TODO: Perhaps extend ClassPropertyAdapter to do these checks?
-
- if (adapter == null)
- throw new RuntimeException(ServiceMessages.noSuchProperty(sourceClass, propertyName));
-
- if (!adapter.isRead())
- throw new RuntimeException(ServiceMessages.readNotSupported(source, propertyName));
-
- if (!propertyType.isAssignableFrom(adapter.getType()))
- throw new RuntimeException(ServiceMessages.propertyTypeMismatch(
- propertyName,
- sourceClass,
- adapter.getType(),
- propertyType));
-
- ClassFab cf = _classFactory.newClass(propertyType);
-
- cf.addField("_source", sourceClass);
-
- cf.addConstructor(new Class[]
- { sourceClass }, null, "_source = $1;");
-
- String body = format("return _source.%s();", adapter.getReadMethod().getName());
-
- MethodSignature sig = new MethodSignature(propertyType, "_delegate", null, null);
- cf.addMethod(Modifier.PRIVATE, sig, body);
-
- String toString = format("<Shadow: property %s of %s>", propertyName, source);
-
- cf.proxyMethodsToDelegate(propertyType, "_delegate()", toString);
-
- Class shadowClass = cf.createClass();
-
- try
- {
- Constructor cc = shadowClass.getConstructors()[0];
-
- Object instance = cc.newInstance(source);
-
- return propertyType.cast(instance);
- }
- catch (Exception ex)
- {
- // Should not be reachable
- throw new RuntimeException(ex);
- }
-
- }
-
-}
+package org.apache.tapestry.ioc.internal.services;
+
+import static java.lang.String.format;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.MethodSignature;
+import org.apache.tapestry.ioc.services.PropertyAccess;
+import org.apache.tapestry.ioc.services.PropertyAdapter;
+import org.apache.tapestry.ioc.services.PropertyShadowBuilder;
+
+public class PropertyShadowBuilderImpl implements PropertyShadowBuilder
+{
+ private final ClassFactory _classFactory;
+
+ private final PropertyAccess _propertyAccess;
+
+ public PropertyShadowBuilderImpl(ClassFactory classFactory, PropertyAccess propertyAccess)
+ {
+ _classFactory = classFactory;
+ _propertyAccess = propertyAccess;
+ }
+
+ public <T> T build(Object source, String propertyName, Class<T> propertyType)
+ {
+ Class sourceClass = source.getClass();
+ PropertyAdapter adapter = _propertyAccess.getAdapter(sourceClass).getPropertyAdapter(
+ propertyName);
+
+ // TODO: Perhaps extend ClassPropertyAdapter to do these checks?
+
+ if (adapter == null)
+ throw new RuntimeException(ServiceMessages.noSuchProperty(sourceClass, propertyName));
+
+ if (!adapter.isRead())
+ throw new RuntimeException(ServiceMessages.readNotSupported(source, propertyName));
+
+ if (!propertyType.isAssignableFrom(adapter.getType()))
+ throw new RuntimeException(ServiceMessages.propertyTypeMismatch(
+ propertyName,
+ sourceClass,
+ adapter.getType(),
+ propertyType));
+
+ ClassFab cf = _classFactory.newClass(propertyType);
+
+ cf.addField("_source", Modifier.PRIVATE | Modifier.FINAL, sourceClass);
+
+ cf.addConstructor(new Class[]
+ { sourceClass }, null, "_source = $1;");
+
+ String body = format("return _source.%s();", adapter.getReadMethod().getName());
+
+ MethodSignature sig = new MethodSignature(propertyType, "_delegate", null, null);
+ cf.addMethod(Modifier.PRIVATE, sig, body);
+
+ String toString = format("<Shadow: property %s of %s>", propertyName, source);
+
+ cf.proxyMethodsToDelegate(propertyType, "_delegate()", toString);
+
+ Class shadowClass = cf.createClass();
+
+ try
+ {
+ Constructor cc = shadowClass.getConstructors()[0];
+
+ Object instance = cc.newInstance(source);
+
+ return propertyType.cast(instance);
+ }
+ catch (Exception ex)
+ {
+ // Should not be reachable
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/StrategyBuilderImpl.java Sun Mar 18 17:10:38 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -37,8 +37,8 @@
{
Class<S> interfaceClass = registry.getAdapterType();
- // TODO: Could cache the implClass by interfaceClass ...
-
+ // TODO: Could cache the implClass by interfaceClass ...
+
Class implClass = createImplClass(interfaceClass);
try
@@ -59,7 +59,7 @@
String interfaceClassName = interfaceClass.getName();
- cf.addField("_registry", StrategyRegistry.class);
+ cf.addField("_registry", Modifier.PRIVATE | Modifier.FINAL, StrategyRegistry.class);
cf.addConstructor(new Class[]
{ StrategyRegistry.class }, null, "_registry = $1;");
@@ -72,7 +72,7 @@
MethodSignature sig = mi.next();
// TODO: Checks for methods that don't have at least one parameter, or don't have a
- // compatible 1st parameter. Currently, we'll get a Javassist exception.
+ // compatible 1st parameter. Currently, we'll get a Javassist exception.
builder.clear();
builder.begin();
Modified: tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFab.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFab.java?view=diff&rev=519755&r1=519754&r2=519755
==============================================================================
--- tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFab.java (original)
+++ tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/ClassFab.java Sun Mar 18 17:10:38 2007
@@ -55,6 +55,9 @@
*/
void addField(String name, Class type);
+ /** Adds a new field with the provided modifiers. */
+ void addField(String name, int modifiers, Class Type);
+
/**
* Adds a method. The method is a public instance method.
*