You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2010/01/26 17:02:55 UTC
svn commit: r903293 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/internal/services/
main/java/org/apache/tapestry5/internal/transform/
main/java/org/apache/tapestry5/services/
main/resources/org/apache/tapestry5/inte...
Author: hlship
Date: Tue Jan 26 16:02:54 2010
New Revision: 903293
URL: http://svn.apache.org/viewvc?rev=903293&view=rev
Log:
Build new methods onto ClassTransformation to match fields and methods, returning TransformFields and TransformMethods
Add assignIndirect() methods to TransformField
Add extend() method to TransformMethod
Removed:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/transform/MixinWorkerTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BlockInjectionProvider.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectContainerWorker.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldFilter.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodFilter.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BlockInjectionProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BlockInjectionProvider.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BlockInjectionProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BlockInjectionProvider.java Tue Jan 26 16:02:54 2010
@@ -25,6 +25,7 @@
import org.apache.tapestry5.services.ComponentValueProvider;
import org.apache.tapestry5.services.InjectionProvider;
import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.TransformMethod;
/**
* Identifies fields of type {@link Block} that have the {@link Inject} annotation and converts them
@@ -57,8 +58,10 @@
}
};
- transformation.assignFieldIndirect(fieldName,
- TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE, provider);
+ TransformMethod method = transformation
+ .getMethod(TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE);
+
+ transformation.getField(fieldName).assignIndirect(method, provider);
return true; // claim the field
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalClassTransformationImpl.java Tue Jan 26 16:02:54 2010
@@ -17,6 +17,7 @@
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.Modifier;
+import java.util.Collection;
import java.util.Collections;
import java.util.Formatter;
import java.util.List;
@@ -29,6 +30,7 @@
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.internal.InternalComponentResources;
+import org.apache.tapestry5.ioc.Predicate;
import org.apache.tapestry5.ioc.internal.services.CtClassSource;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.Defense;
@@ -93,6 +95,11 @@
}
+ public int compareTo(TransformMethod o)
+ {
+ return sig.compareTo(o.getSignature());
+ }
+
public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
{
if (annotations == null)
@@ -101,11 +108,27 @@
return findAnnotationInList(annotationClass, annotations);
}
- @Override
public TransformMethodSignature getSignature()
{
return sig;
}
+
+ public void extend(String body)
+ {
+ failIfFrozen();
+
+ try
+ {
+ method.insertAfter(body);
+ }
+ catch (CannotCompileException ex)
+ {
+ throw new MethodCompileException(
+ ServicesMessages.methodCompileError(sig, body, ex), body, ex);
+ }
+
+ addMethodToDescription("extend", sig, body);
+ }
}
class TransformFieldImpl implements TransformField
@@ -142,6 +165,11 @@
primitive = ClassFabUtils.isPrimitiveType(type);
}
+ public int compareTo(TransformField o)
+ {
+ return name.compareTo(o.getName());
+ }
+
public String getName()
{
return name;
@@ -228,6 +256,40 @@
removeField(name);
}
+
+ public <T> void assignIndirect(TransformMethod method, ComponentValueProvider<T> provider)
+ {
+ Defense.notNull(method, "method");
+ Defense.notNull(provider, "provider");
+
+ String providerFieldName = addInjectedField(ComponentValueProvider.class, name
+ + "$provider", provider);
+
+ CtClass fieldType = null;
+
+ try
+ {
+ fieldType = field.getType();
+ }
+ catch (NotFoundException ex)
+ {
+ throw new RuntimeException(ex);
+ }
+
+ String body = String.format("%s = (%s) %s.get(%s);", name, fieldType.getName(),
+ providerFieldName, resourcesFieldName);
+
+ extendMethod(method.getSignature(), body);
+
+ makeReadOnly(name);
+ }
+
+ @Override
+ public <T> void assignIndirect(TransformMethodSignature signature,
+ ComponentValueProvider<T> provider)
+ {
+ assignIndirect(getMethod(signature), provider);
+ }
}
private final Map<TransformMethodSignature, TransformMethodImpl> methods = CollectionFactory
@@ -485,17 +547,7 @@
public <T extends Annotation> T getMethodAnnotation(TransformMethodSignature signature,
Class<T> annotationClass)
{
- failIfFrozen();
-
- CtMethod method = findDeclaredOrSuperclassMethod(signature);
-
- if (method == null)
- throw new IllegalArgumentException(ServicesMessages
- .noDeclaredMethod(ctClass, signature));
-
- List<Annotation> annotations = findMethodAnnotations(method);
-
- return findAnnotationInList(annotationClass, annotations);
+ return getMethod(signature).getAnnotation(annotationClass);
}
/**
@@ -527,20 +579,6 @@
return findAnnotationInList(annotationClass, getClassAnnotations());
}
- private List<Annotation> findMethodAnnotations(CtMethod method)
- {
- List<Annotation> annotations = methodAnnotations.get(method);
-
- if (annotations == null)
- {
- annotations = extractAnnotations(method);
-
- methodAnnotations.put(method, annotations);
- }
-
- return annotations;
- }
-
private List<Annotation> extractAnnotations(CtMember member)
{
try
@@ -713,11 +751,13 @@
}
}
- private void recordMethod(CtMethod method, boolean asNew)
+ private TransformMethodImpl recordMethod(CtMethod method, boolean asNew)
{
TransformMethodImpl tmi = new TransformMethodImpl(method, asNew);
methods.put(tmi.getSignature(), tmi);
+
+ return tmi;
}
/**
@@ -891,40 +931,12 @@
public void extendMethod(TransformMethodSignature methodSignature, String methodBody)
{
- failIfFrozen();
-
- CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
-
- try
- {
- method.insertAfter(methodBody);
- }
- catch (CannotCompileException ex)
- {
- throw new MethodCompileException(ServicesMessages.methodCompileError(methodSignature,
- methodBody, ex), methodBody, ex);
- }
-
- addMethodToDescription("extend", methodSignature, methodBody);
+ getMethod(methodSignature).extend(methodBody);
}
public void extendExistingMethod(TransformMethodSignature methodSignature, String methodBody)
{
- failIfFrozen();
-
- CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
-
- try
- {
- method.insertAfter(methodBody);
- }
- catch (CannotCompileException ex)
- {
- throw new MethodCompileException(ServicesMessages.methodCompileError(methodSignature,
- methodBody, ex), methodBody, ex);
- }
-
- addMethodToDescription("extend existing", methodSignature, methodBody);
+ extendMethod(methodSignature, methodBody);
}
public void copyMethod(TransformMethodSignature sourceMethod, int modifiers,
@@ -935,7 +947,10 @@
CtClass returnType = findCtClass(sourceMethod.getReturnType());
CtClass[] parameters = buildCtClassList(sourceMethod.getParameterTypes());
CtClass[] exceptions = buildCtClassList(sourceMethod.getExceptionTypes());
- CtMethod source = findDeclaredOrSuperclassMethod(sourceMethod);
+
+ TransformMethodImpl tmi = findOrOverrideMethod(sourceMethod);
+
+ CtMethod source = tmi.method;
try
{
@@ -971,12 +986,12 @@
{
failIfFrozen();
- CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
+ TransformMethodImpl tmi = findOrOverrideMethod(methodSignature);
CtClass exceptionCtType = findCtClass(exceptionType);
try
{
- method.addCatch(body, exceptionCtType);
+ tmi.method.addCatch(body, exceptionCtType);
}
catch (CannotCompileException ex)
{
@@ -991,11 +1006,11 @@
{
failIfFrozen();
- CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
+ TransformMethodImpl tmi = findOrOverrideMethod(methodSignature);
try
{
- method.insertBefore(methodBody);
+ tmi.method.insertBefore(methodBody);
}
catch (CannotCompileException ex)
{
@@ -1037,33 +1052,35 @@
formatter.format("\n%s\n\n", methodBody);
}
- private CtMethod findDeclaredOrSuperclassMethod(TransformMethodSignature methodSignature)
+ public TransformMethod getMethod(TransformMethodSignature signature)
{
- CtMethod method = findDeclaredMethod(methodSignature);
+ failIfFrozen();
- if (method != null)
- return method;
+ return findOrOverrideMethod(signature);
+ }
- CtMethod result = addOverrideOfSuperclassMethod(methodSignature);
+ private TransformMethodImpl findOrOverrideMethod(TransformMethodSignature signature)
+ {
+ TransformMethodImpl result = methods.get(signature);
if (result != null)
return result;
- throw new IllegalArgumentException(ServicesMessages.noDeclaredMethod(ctClass,
- methodSignature));
- }
+ result = addOverrideOfSuperclassMethod(signature);
- private CtMethod findDeclaredMethod(TransformMethodSignature methodSignature)
- {
- TransformMethodImpl tmi = methods.get(methodSignature);
+ if (result != null)
+ return result;
+
+ throw new IllegalArgumentException(String.format("Class %s does not declare method '%s'.",
+ ctClass.getName(), signature));
- return tmi == null ? null : tmi.method;
}
// TODO: Rework this method for efficiency, i.e., so that we can leverage the methods
// map in parent InternalClassTransformImpls, rather than the exhaustive
// search.
- private CtMethod addOverrideOfSuperclassMethod(TransformMethodSignature methodSignature)
+ private TransformMethodImpl addOverrideOfSuperclassMethod(
+ TransformMethodSignature methodSignature)
{
try
{
@@ -1073,15 +1090,14 @@
{
if (match(method, methodSignature))
{
- // TODO: If the method is not overridable (i.e. private, or final)?
+ // TODO: What if the method is not overridable (i.e. private, or final)?
// Perhaps we should limit it to just public methods.
CtMethod newMethod = CtNewMethod.delegator(method, ctClass);
ctClass.addMethod(newMethod);
- recordMethod(newMethod, true);
-
- return newMethod;
+ // Record it as a new method.
+ return recordMethod(newMethod, true);
}
}
}
@@ -1150,7 +1166,7 @@
return findFields(filter);
}
- public List<String> findFields(FieldFilter filter)
+ public List<String> findFields(final FieldFilter filter)
{
failIfFrozen();
@@ -1169,48 +1185,67 @@
return result;
}
- public List<TransformMethodSignature> findMethodsWithAnnotation(
- final Class<? extends Annotation> annotationClass)
+ public List<TransformField> matchFields(Predicate<TransformField> predicate)
{
failIfFrozen();
- List<TransformMethodSignature> result = CollectionFactory.newList();
+ return InternalUtils.matchAndSort(fields.values(), predicate);
+ }
- for (CtMethod method : ctClass.getDeclaredMethods())
+ @Override
+ public List<TransformField> matchFieldsWithAnnotation(
+ final Class<? extends Annotation> annotationClass)
+ {
+ return matchFields(new Predicate<TransformField>()
{
- List<Annotation> annotations = findMethodAnnotations(method);
-
- if (findAnnotationInList(annotationClass, annotations) != null)
+ @Override
+ public boolean accept(TransformField field)
{
- TransformMethodSignature sig = getMethodSignature(method);
- result.add(sig);
+ return field.getAnnotation(annotationClass) != null;
}
- }
+ });
+ }
- Collections.sort(result);
+ public List<TransformMethodSignature> findMethodsWithAnnotation(
+ final Class<? extends Annotation> annotationClass)
+ {
+ List<TransformMethod> methods = matchMethods(new Predicate<TransformMethod>()
+ {
+ public boolean accept(TransformMethod method)
+ {
+ return method.getAnnotation(annotationClass) != null;
+ };
+ });
- return result;
+ return toMethodSignatures(methods);
}
- public List<TransformMethodSignature> findMethods(MethodFilter filter)
+ public List<TransformMethodSignature> findMethods(final MethodFilter filter)
{
Defense.notNull(filter, "filter");
- List<TransformMethodSignature> result = CollectionFactory.newList();
-
- for (TransformMethodSignature sig : methods.keySet())
+ List<TransformMethod> methods = matchMethods(new Predicate<TransformMethod>()
{
- if (filter.accept(sig))
- result.add(sig);
- }
+ public boolean accept(TransformMethod object)
+ {
+ return filter.accept(object.getSignature());
+ };
+ });
- Collections.sort(result);
+ return toMethodSignatures(methods);
+ }
- return result;
+ public List<TransformMethod> matchMethods(final Predicate<TransformMethod> predicate)
+ {
+ failIfFrozen();
+
+ return InternalUtils.matchAndSort(methods.values(), predicate);
}
private TransformMethodSignature getMethodSignature(CtMethod method)
{
+ failIfFrozen();
+
TransformMethodSignature result = methodSignatures.get(method);
if (result == null)
{
@@ -1393,7 +1428,7 @@
{
Defense.notNull(type, "type");
Defense.notNull(provider, "provider");
-
+
TransformField field = addTransformField(Modifier.PRIVATE | Modifier.FINAL, type.getName(),
suggestedName);
@@ -1503,7 +1538,7 @@
{
Defense.notNull(signature, "signature");
- return findDeclaredMethod(signature) != null;
+ return methods.containsKey(signature);
}
/**
@@ -2072,7 +2107,8 @@
{
Defense.notNull(signature, "signature");
- CtMethod method = findDeclaredOrSuperclassMethod(signature);
+ TransformMethodImpl tmi = findOrOverrideMethod(signature);
+ CtMethod method = tmi.method;
int lineNumber = method.getMethodInfo2().getLineNumber(0);
CtClass enclosingClass = method.getDeclaringClass();
@@ -2103,23 +2139,27 @@
return "$" + constructorArgs.size();
}
- public <T> void assignFieldIndirect(String fieldName, TransformMethodSignature methodSig,
- ComponentValueProvider<T> provider)
+ private static List<TransformMethodSignature> toMethodSignatures(List<TransformMethod> input)
{
- Defense.notBlank(fieldName, "fieldName");
- Defense.notNull(methodSig, "methodSig");
- Defense.notNull(provider, "provider");
+ List<TransformMethodSignature> result = CollectionFactory.newList();
- String providerFieldName = addInjectedField(ComponentValueProvider.class, fieldName
- + "$provider", provider);
+ for (TransformMethod m : input)
+ {
+ result.add(m.getSignature());
+ }
- CtClass fieldType = getFieldCtType(fieldName);
+ return result;
+ }
- String body = String.format("%s = (%s) %s.get(%s);", fieldName, fieldType.getName(),
- providerFieldName, resourcesFieldName);
+ private static List<String> toFieldNames(List<TransformField> fields)
+ {
+ List<String> result = CollectionFactory.newList();
- extendMethod(methodSig, body);
+ for (TransformField f : fields)
+ {
+ result.add(f.getName());
+ }
- makeReadOnly(fieldName);
+ return result;
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java Tue Jan 26 16:02:54 2010
@@ -52,11 +52,6 @@
return MESSAGES.format("error-adding-method", ctClass.getName(), methodName, cause);
}
- static String noDeclaredMethod(CtClass ctClass, TransformMethodSignature methodSignature)
- {
- return MESSAGES.format("no-declared-method", ctClass.getName(), methodSignature);
- }
-
static String classNotTransformed(String className)
{
return MESSAGES.format("class-not-transformed", className);
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ComponentWorker.java Tue Jan 26 16:02:54 2010
@@ -35,12 +35,13 @@
import org.apache.tapestry5.services.ComponentClassTransformWorker;
import org.apache.tapestry5.services.ComponentValueProvider;
import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.TransformField;
/**
* Finds fields with the {@link org.apache.tapestry5.annotations.Component} annotation and updates
* the model. Also
- * checks for the {@link Mixins} and {@link MixinClasses} annotations and uses them to update the
- * {@link ComponentModel}.
+ * checks for the {@link Mixins} and {@link MixinClasses} annotations and uses them to update the {@link ComponentModel}
+ * .
*/
public class ComponentWorker implements ComponentClassTransformWorker
{
@@ -53,18 +54,20 @@
public void transform(ClassTransformation transformation, MutableComponentModel model)
{
- for (String fieldName : transformation.findFieldsWithAnnotation(Component.class))
+ for (TransformField field : transformation.matchFieldsWithAnnotation(Component.class))
{
- Component annotation = transformation.getFieldAnnotation(fieldName, Component.class);
+ Component annotation = field.getAnnotation(Component.class);
- transformation.claimField(fieldName, annotation);
+ field.claim(annotation);
String annotationId = annotation.id();
+ String fieldName = field.getName();
+
final String id = InternalUtils.isNonBlank(annotationId) ? annotationId : InternalUtils
.stripMemberName(fieldName);
- String type = transformation.getFieldType(fieldName);
+ String type = field.getType();
Location location = new StringLocation(String.format("%s.%s", transformation
.getClassName(), fieldName), 0);
@@ -82,25 +85,23 @@
}
ComponentValueProvider<Object> provider = new ComponentValueProvider<Object>()
- {
+ {
public Object get(ComponentResources resources)
{
return resources.getEmbeddedComponent(id);
}
};
- transformation.assignFieldIndirect(fieldName,
- TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, provider);
+ field.assignIndirect(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, provider);
- addMixinClasses(fieldName, transformation, embedded);
- addMixinTypes(fieldName, transformation, embedded);
+ addMixinClasses(field, embedded);
+ addMixinTypes(field, embedded);
}
}
- private void addMixinClasses(String fieldName, ClassTransformation transformation,
- MutableEmbeddedComponentModel model)
+ private void addMixinClasses(TransformField field, MutableEmbeddedComponentModel model)
{
- MixinClasses annotation = transformation.getFieldAnnotation(fieldName, MixinClasses.class);
+ MixinClasses annotation = field.getAnnotation(MixinClasses.class);
if (annotation == null)
return;
@@ -109,7 +110,7 @@
if (!orderEmpty && annotation.order().length != annotation.value().length)
throw new TapestryException(TransformMessages.badMixinConstraintLength(annotation,
- fieldName), model, null);
+ field.getName()), model, null);
for (int i = 0; i < annotation.value().length; i++)
{
@@ -120,10 +121,9 @@
}
}
- private void addMixinTypes(String fieldName, ClassTransformation transformation,
- MutableEmbeddedComponentModel model)
+ private void addMixinTypes(TransformField field, MutableEmbeddedComponentModel model)
{
- Mixins annotation = transformation.getFieldAnnotation(fieldName, Mixins.class);
+ Mixins annotation = field.getAnnotation(Mixins.class);
if (annotation == null)
return;
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectContainerWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectContainerWorker.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectContainerWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectContainerWorker.java Tue Jan 26 16:02:54 2010
@@ -14,8 +14,6 @@
package org.apache.tapestry5.internal.transform;
-import java.util.List;
-
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.internal.services.ComponentClassCache;
@@ -25,6 +23,7 @@
import org.apache.tapestry5.services.ComponentClassTransformWorker;
import org.apache.tapestry5.services.ComponentValueProvider;
import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.TransformField;
/**
* Identifies the {@link org.apache.tapestry5.annotations.InjectContainer} annotation and adds code
@@ -42,11 +41,12 @@
public void transform(ClassTransformation transformation, MutableComponentModel model)
{
- List<String> names = transformation.findFieldsWithAnnotation(InjectContainer.class);
-
- for (final String fieldName : names)
+ for (final TransformField field : transformation
+ .matchFieldsWithAnnotation(InjectContainer.class))
{
- final String fieldTypeName = transformation.getFieldType(fieldName);
+ final String fieldName = field.getName();
+
+ final String fieldTypeName = field.getType();
final String componentClassName = model.getComponentClassName();
@@ -72,8 +72,7 @@
}
};
- transformation.assignFieldIndirect(fieldName,
- TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, provider);
+ field.assignIndirect(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, provider);
}
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/MixinWorker.java Tue Jan 26 16:02:54 2010
@@ -14,8 +14,6 @@
package org.apache.tapestry5.internal.transform;
-import java.util.List;
-
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.Mixin;
import org.apache.tapestry5.internal.InternalComponentResources;
@@ -26,6 +24,7 @@
import org.apache.tapestry5.services.ComponentClassTransformWorker;
import org.apache.tapestry5.services.ComponentValueProvider;
import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.TransformField;
/**
* Supports the {@link org.apache.tapestry5.annotations.Mixin} annotation, which allows a mixin to
@@ -45,19 +44,17 @@
public void transform(ClassTransformation transformation, MutableComponentModel model)
{
- List<String> fields = transformation.findFieldsWithAnnotation(Mixin.class);
-
- for (String fieldName : fields)
+ for (TransformField field : transformation.matchFieldsWithAnnotation(Mixin.class))
{
- Mixin annotation = transformation.getFieldAnnotation(fieldName, Mixin.class);
+ Mixin annotation = field.getAnnotation(Mixin.class);
- transformation.claimField(fieldName, annotation);
+ field.claim(annotation);
String mixinType = annotation.value();
String[] order = annotation.order();
- String fieldType = transformation.getFieldType(fieldName);
+ String fieldType = field.getType();
final String mixinClassName = InternalUtils.isBlank(mixinType) ? fieldType : resolver
.resolveMixinTypeToClassName(mixinType);
@@ -74,8 +71,7 @@
}
};
- transformation.assignFieldIndirect(fieldName,
- TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, provider);
+ field.assignIndirect(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, provider);
}
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClassTransformation.java Tue Jan 26 16:02:54 2010
@@ -14,14 +14,17 @@
package org.apache.tapestry5.services;
+import java.lang.annotation.Annotation;
+import java.util.List;
+
import javassist.CtBehavior;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.ioc.AnnotationProvider;
+import org.apache.tapestry5.ioc.Predicate;
import org.slf4j.Logger;
-import java.lang.annotation.Annotation;
-import java.util.List;
+import com.sun.source.tree.MethodTree;
/**
* Contains class-specific information used when transforming a raw component class into an
@@ -87,10 +90,20 @@
* Generates a list of the names of declared instance fields that have the indicated annotation.
* Non-private and
* static fields are ignored. Only the names of private instance fields are returned.
+ *
+ * @deprecated Use {@link #matchFieldsWithAnnotation(Class)} instead
*/
List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass);
/**
+ * Returns a sorted list of declared instance fields with the indicated annotation. Non-private
+ * and static fields are ignored. Claimed fields are also ignored.
+ *
+ * @since 5.2.0
+ */
+ List<TransformField> matchFieldsWithAnnotation(Class<? extends Annotation> annotationClass);
+
+ /**
* Finds all methods defined in the class that are marked with the provided annotation.
*
* @param annotationClass
@@ -108,20 +121,42 @@
* @return a list of matching method signatures (which may be empty) in ascending order (by
* method name), but
* descending order (by parameter count) within overrides of a single method name.
+ * @deprecated Use {@link #matchMethods(Predicate)} instead
*/
List<TransformMethodSignature> findMethods(MethodFilter filter);
/**
+ * Finds all methods matched by the provided predicate.
+ *
+ * @param predicate
+ * Used to filter the list
+ * @return a list of matching methods (which may be empty) in ascending order (by
+ * method name), but descending order (by parameter count) within overrides of a single method name.
+ */
+ List<TransformMethod> matchMethods(Predicate<TransformMethod> predicate);
+
+ /**
* Finds all unclaimed fields matched by the provided filter. Only considers private instance
* fields.
*
* @param filter
* passed each field name and field type
* @return the names of all matched fields, in ascending order
+ * @deprecated Use {@link #matchFields(Predicate)} instead
*/
List<String> findFields(FieldFilter filter);
/**
+ * Finds all unclaimed fields matched by the provided predicate. Only considers instance fields.
+ *
+ * @param predicate
+ * used for matching
+ * @return sorted list of matching fields
+ * @since 5.2.0
+ */
+ List<TransformField> matchFields(Predicate<TransformField> predicate);
+
+ /**
* Finds an annotation on a declared instance field.
*
* @param <T>
@@ -342,14 +377,15 @@
* the body of code
* @throws org.apache.tapestry5.internal.services.MethodCompileException
* if the provided Javassist method body can not be compiled
- * @see #extendExistingMethod(TransformMethodSignature, String)
+ * @deprecated Use {@link TransformMethod#extend(String)} instead
*/
void extendMethod(TransformMethodSignature methodSignature, String methodBody);
/**
* Like {@link #extendMethod(TransformMethodSignature, String)}, but the extension does not mark
* the method as new,
- * and field changes <em>will</em> be processed.
+ * and field changes <em>will</em> be processed. Note: at some point, this is not longer true; extend and
+ * extendMethod work identically.
*
* @param methodSignature
* signature of the method to extend
@@ -358,6 +394,7 @@
* @throws org.apache.tapestry5.internal.services.MethodCompileException
* if the provided method body can not be compiled
* @see #prefixMethod(TransformMethodSignature, String)
+ * @deprecated Use {@link TransformMethod#extend(String) instead}
*/
void extendExistingMethod(TransformMethodSignature methodSignature, String methodBody);
@@ -510,21 +547,16 @@
boolean isMethodOverride(TransformMethodSignature methodSignature);
/**
- * Uses {@link #extendMethod(TransformMethodSignature, String)} to make an assignment to
- * a field within the provided method. In addition, the field is marked as read-only. This
- * is an alternative to {@link #injectFieldIndirect(String, ComponentValueProvider)} for values
- * that <em>can not</em> be calculated at the constructor.
+ * Locates and returns the method if declared in this class; if not, locates
+ * a super-class method that is implemented into this class. In the latter
+ * case, the method will be considered "new" (i.e., no field transformations),
+ * as with {@link #extendMethod(TransformMethodSignature, String)}).
*
- * @param <T>
- * @param fieldName
- * name of field to assign
- * @param methodSig
- * identifies the method where the assignment will occur, often this is
- * {@link TransformConstants#CONTAINING_PAGE_DID_LOAD_SIGNATURE}
- * @param provider
- * provides the value of the field
+ * @param signature
+ * identifies the method to obtain
+ * @throw RuntimeException if the signature does not match a declared method of this
+ * class, or a overridable method of a superclass
* @since 5.2.0
*/
- <T> void assignFieldIndirect(String fieldName, TransformMethodSignature methodSig,
- ComponentValueProvider<T> provider);
- }
+ TransformMethod getMethod(TransformMethodSignature signature);
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldFilter.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldFilter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/FieldFilter.java Tue Jan 26 16:02:54 2010
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2010 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.
@@ -14,8 +14,12 @@
package org.apache.tapestry5.services;
+import org.apache.tapestry5.ioc.Predicate;
+
/**
* Used by {@link ClassTransformation#findFields(FieldFilter)} to identify which fields to keep.
+ *
+ * @deprecated New APIs use {@link Predicate} instead
*/
public interface FieldFilter
{
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodFilter.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodFilter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MethodFilter.java Tue Jan 26 16:02:54 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2010 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.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,8 +14,12 @@
package org.apache.tapestry5.services;
+import org.apache.tapestry5.ioc.Predicate;
+
/**
* Used by {@link ClassTransformation#findMethods(MethodFilter)} to accept or reject each method.
+ *
+ * @deprecated New APIs use {@link Predicate} instead
*/
public interface MethodFilter
{
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java Tue Jan 26 16:02:54 2010
@@ -23,7 +23,7 @@
*
* @since 5.2.0
*/
-public interface TransformField extends AnnotationProvider
+public interface TransformField extends AnnotationProvider, Comparable<TransformField>
{
/**
* Returns the name of the field.
@@ -72,4 +72,25 @@
* identifies the field containing (via injection) an instance of {@link FieldValueConduit}
*/
void replaceAccess(TransformField conduitField);
+
+ /**
+ * Extends the indicated method to add an assignment of the field with
+ * the value obtained by the provider. This is used when a value
+ * to be provided can not be provided from within the transformed class'
+ * constructor.
+ *
+ * @param <T>
+ * @param method
+ * identifies the method where the assignment will occur, often this is
+ * {@link TransformConstants#CONTAINING_PAGE_DID_LOAD_SIGNATURE}
+ * @param provider
+ * provides the value of the field
+ */
+ <T> void assignIndirect(TransformMethod method, ComponentValueProvider<T> provider);
+
+ /**
+ * Alternate version of {@link #assignIndirect(TransformMethod, ComponentValueProvider)} that operates using a
+ * method signature.
+ */
+ <T> void assignIndirect(TransformMethodSignature signature, ComponentValueProvider<T> provider);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java Tue Jan 26 16:02:54 2010
@@ -19,14 +19,34 @@
/**
* A method defined by (or created within) a {@link ClassTransformation}, allowing
* for access and manipulation of the method.
+ * <p>
+ * The natural sorting order of TransformMethods is the same as {@link TransformMethodSignature}.
*
* @since 5.2.0
*/
-public interface TransformMethod extends AnnotationProvider
+public interface TransformMethod extends AnnotationProvider, Comparable<TransformMethod>
{
/**
* @return the signature for the method, defining name, visibility, return type, parameter types and thrown
* exceptions
*/
TransformMethodSignature getSignature();
+
+ /**
+ * Extends an existing method. The provided method body is inserted at the end of the existing
+ * method (i.e. {@link javassist.CtBehavior#insertAfter(java.lang.String)}). To access or change
+ * the return value, use the <code>$_</code> pseudo variable.
+ * <p/>
+ * The method may be declared in the class, or may be inherited from a super-class. For inherited methods, a method
+ * body is added that first invokes the super implementation.
+ * <p/>
+ * The extended method is considered <em>new</em>. New methods <em>are not</em> scanned for removed fields, field
+ * access changes, etc.
+ *
+ * @param body
+ * the body of Javassist psuedo-code
+ * @throws RuntimeException
+ * if the provided Javassist method body can not be compiled
+ */
+ void extend(String body);
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties Tue Jan 26 16:02:54 2010
@@ -17,7 +17,6 @@
The current element is established with the first call to element() and is \
maintained across subsequent calls.
error-adding-method=Error adding method %s to class %s: %s
-no-declared-method=Class %s does not declare method '%s'.
class-not-transformed=Class %s was not transformed for use as a component; this can happen if it is an interface, or was not in a package subject to component transformation.
missing-template-resource=Template resource %s does not exist.
content-inside-body-not-allowed=Content inside a Tapestry body element is not allowed (at %s). The content has been ignored.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java?rev=903293&r1=903292&r2=903293&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/TextOnlyOnDisabledTextField.java Tue Jan 26 16:02:54 2010
@@ -1,10 +1,10 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 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.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,17 +14,13 @@
package org.apache.tapestry5.integration.app1.components;
-import org.apache.tapestry5.corelib.components.TextField;
import org.apache.tapestry5.annotations.Mixin;
-import org.apache.tapestry5.integration.app1.mixins.TextOnlyOnDisabled;
+import org.apache.tapestry5.corelib.components.TextField;
-/**
- *
- */
public class TextOnlyOnDisabledTextField extends TextField
{
+ @SuppressWarnings("unused")
+ @Mixin(value = "textonlyondisabled", order = "after:*")
+ private Object theMixin;
- @Mixin(order = "after:*")
- private TextOnlyOnDisabled theMixin;
-
}