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:20 UTC

svn commit: r903289 - in /tapestry/tapestry5/trunk/tapestry-core/src/main: java/org/apache/tapestry5/internal/services/ java/org/apache/tapestry5/services/ resources/org/apache/tapestry5/internal/services/

Author: hlship
Date: Tue Jan 26 16:02:19 2010
New Revision: 903289

URL: http://svn.apache.org/viewvc?rev=903289&view=rev
Log:
Begin rebuilding the ClassTransformation API around the new TransformField and TransformMethod interfaces

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java   (with props)
Modified:
    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/services/ClassTransformation.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties

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=903289&r1=903288&r2=903289&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:19 2010
@@ -47,6 +47,8 @@
 import org.apache.tapestry5.services.FieldFilter;
 import org.apache.tapestry5.services.FieldValueConduit;
 import org.apache.tapestry5.services.MethodFilter;
+import org.apache.tapestry5.services.TransformField;
+import org.apache.tapestry5.services.TransformMethod;
 import org.apache.tapestry5.services.TransformMethodSignature;
 import org.apache.tapestry5.services.TransformUtils;
 import org.slf4j.Logger;
@@ -56,6 +58,7 @@
  */
 public final class InternalClassTransformationImpl implements InternalClassTransformation
 {
+
     private static final int INIT_BUFFER_SIZE = 100;
 
     private boolean frozen;
@@ -72,6 +75,122 @@
 
     private final CtClass providerType;
 
+    class TransformMethodImpl implements TransformMethod
+    {
+        final CtMethod method;
+
+        private final TransformMethodSignature sig;
+
+        private List<Annotation> annotations;
+
+        private final boolean added;
+
+        TransformMethodImpl(CtMethod method, boolean added)
+        {
+            this.method = method;
+            this.sig = toMethodSignature(method);
+            this.added = added;
+
+        }
+
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+        {
+            if (annotations == null)
+                annotations = extractAnnotations(method);
+
+            return findAnnotationInList(annotationClass, annotations);
+        }
+
+        @Override
+        public TransformMethodSignature getSignature()
+        {
+            return sig;
+        }
+    }
+
+    class TransformFieldImpl implements TransformField
+    {
+        private final CtField field;
+
+        private final String type;
+
+        private final boolean primitive;
+
+        private boolean added;
+
+        private List<Annotation> annotations;
+
+        private Object claimTag;
+
+        TransformFieldImpl(CtField field, boolean added)
+        {
+            this.field = field;
+            this.added = added;
+
+            try
+            {
+                type = field.getType().getName();
+            }
+            catch (NotFoundException ex)
+            {
+                throw new RuntimeException(ex);
+            }
+
+            primitive = ClassFabUtils.isPrimitiveType(type);
+        }
+
+        public String getName()
+        {
+            return field.getName();
+        }
+
+        public String getType()
+        {
+            return type;
+        }
+
+        public boolean isPrimitive()
+        {
+            return primitive;
+        }
+
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+        {
+            failIfFrozen();
+
+            if (annotations == null)
+                annotations = extractAnnotations(field);
+
+            return findAnnotationInList(annotationClass, annotations);
+        }
+
+        public void claim(Object tag)
+        {
+            Defense.notNull(tag, "tag");
+
+            failIfFrozen();
+
+            if (claimTag != null)
+                throw new IllegalStateException(
+                        String
+                                .format(
+                                        "Field %s of class %s is already claimed by %s and can not be claimed by %s.",
+                                        getName(), ctClass.getName(), claimTag, tag));
+
+            claimTag = tag;
+        }
+
+        public boolean isClaimed()
+        {
+            return claimTag != null;
+        }
+    }
+
+    private final Map<TransformMethodSignature, TransformMethodImpl> methods = CollectionFactory
+            .newMap();
+
+    private Map<String, TransformFieldImpl> fields = CollectionFactory.newMap();
+
     /**
      * Map, keyed on InjectKey, of field name. Injections are always added as protected (not
      * private) fields to support
@@ -79,20 +198,6 @@
      */
     private final Map<InjectionKey, String> injectionCache = CollectionFactory.newMap();
 
-    /**
-     * Map from a field to the annotation objects for that field.
-     */
-    private Map<String, List<Annotation>> fieldAnnotations = CollectionFactory.newMap();
-
-    /**
-     * Used to identify fields that have been "claimed" by other annotations.
-     */
-    private Map<String, Object> claimedFields = CollectionFactory.newMap();
-
-    private Set<String> addedFieldNames = CollectionFactory.newSet();
-
-    private Set<CtBehavior> addedMethods = CollectionFactory.newSet();
-
     // Cache of class annotation
 
     private List<Annotation> classAnnotations;
@@ -143,6 +248,10 @@
             Component.class, "newInstance", new Class[]
             { InternalComponentResources.class }, null);
 
+    private static final TransformMethodSignature GET_COMPONENT_RESOURCES_SIGNATURE = new TransformMethodSignature(
+            Modifier.PUBLIC | Modifier.FINAL, ComponentResources.class.getName(),
+            "getComponentResources", null, null);
+
     /**
      * This is a constructor for a base class.
      */
@@ -164,7 +273,7 @@
 
         logger = componentModel.getLogger();
 
-        preloadMemberNames();
+        preloadMembers();
 
         constructorArgs = CollectionFactory.newList();
         constructor.append("{\n");
@@ -174,11 +283,7 @@
         resourcesFieldName = addInjectedFieldUncached(InternalComponentResources.class,
                 "resources", null);
 
-        TransformMethodSignature sig = new TransformMethodSignature(Modifier.PUBLIC
-                | Modifier.FINAL, ComponentResources.class.getName(), "getComponentResources",
-                null, null);
-
-        addMethod(sig, "return " + resourcesFieldName + ";");
+        addMethod(GET_COMPONENT_RESOURCES_SIGNATURE, "return " + resourcesFieldName + ";");
 
         // The "}" will be added later, inside finish().
     }
@@ -206,7 +311,7 @@
 
         idAllocator = parentTransformation.getIdAllocator();
 
-        preloadMemberNames();
+        preloadMembers();
 
         constructorArgs = parentTransformation.getConstructorArgs();
 
@@ -247,10 +352,8 @@
         // Free up stuff we don't need after freezing.
         // Everything else should be final.
 
-        fieldAnnotations = null;
-        claimedFields = null;
-        addedFieldNames = null;
-        addedMethods = null;
+        fields = null;
+
         classAnnotations = null;
         methodAnnotations = null;
         methodSignatures = null;
@@ -268,25 +371,33 @@
     }
 
     /**
-     * Loads the names of all declared fields and methods into the idAllocator.
+     * Loads all existing fields and methods defined by the class.
      */
+    private void preloadMembers()
+    {
+        preloadFields();
+        preloadMethods();
+    }
 
-    private void preloadMemberNames()
+    private void preloadMethods()
     {
-        verifyFields();
+        for (CtMethod method : ctClass.getDeclaredMethods())
+        {
+            recordMethod(method, false);
 
-        addMemberNames(ctClass.getDeclaredFields());
-        addMemberNames(ctClass.getDeclaredMethods());
+            idAllocator.allocateId(method.getName());
+        }
     }
 
     /**
-     * Invoked during instance construction to check that all fields are either:
+     * Converts and stores {@link CtField} to {@link TransformField}, and checks that each field is
+     * one of:
      * <ul>
      * <li>private</li>
      * <li>static</li>
-     * <li>groovy.lang.MetaClass (for Groovy compatiblility)</li> </li>
+     * <li>groovy.lang.MetaClass (for Groovy compatibility)</li> </li>
      */
-    void verifyFields()
+    private void preloadFields()
     {
         List<String> names = CollectionFactory.newList();
 
@@ -294,6 +405,10 @@
         {
             String name = field.getName();
 
+            idAllocator.allocateId(name);
+
+            fields.put(name, new TransformFieldImpl(field, false));
+
             int modifiers = field.getModifiers();
 
             // Fields must be either static or private.
@@ -318,21 +433,9 @@
             throw new RuntimeException(ServicesMessages.nonPrivateFields(getClassName(), names));
     }
 
-    private void addMemberNames(CtMember[] members)
-    {
-        for (CtMember member : members)
-        {
-            idAllocator.allocateId(member.getName());
-        }
-    }
-
     public <T extends Annotation> T getFieldAnnotation(String fieldName, Class<T> annotationClass)
     {
-        failIfFrozen();
-
-        List<Annotation> annotations = findFieldAnnotations(fieldName);
-
-        return findAnnotationInList(annotationClass, annotations);
+        return getField(fieldName).getAnnotation(annotationClass);
     }
 
     public <T extends Annotation> T getMethodAnnotation(TransformMethodSignature signature,
@@ -340,7 +443,7 @@
     {
         failIfFrozen();
 
-        CtMethod method = findMethod(signature);
+        CtMethod method = findDeclaredOrSuperclassMethod(signature);
 
         if (method == null)
             throw new IllegalArgumentException(ServicesMessages
@@ -380,19 +483,6 @@
         return findAnnotationInList(annotationClass, getClassAnnotations());
     }
 
-    private List<Annotation> findFieldAnnotations(String fieldName)
-    {
-        List<Annotation> annotations = fieldAnnotations.get(fieldName);
-
-        if (annotations == null)
-        {
-            annotations = findAnnotationsForField(fieldName);
-            fieldAnnotations.put(fieldName, annotations);
-        }
-
-        return annotations;
-    }
-
     private List<Annotation> findMethodAnnotations(CtMethod method)
     {
         List<Annotation> annotations = methodAnnotations.get(method);
@@ -407,13 +497,6 @@
         return annotations;
     }
 
-    private List<Annotation> findAnnotationsForField(String fieldName)
-    {
-        CtField field = findDeclaredCtField(fieldName);
-
-        return extractAnnotations(field);
-    }
-
     private List<Annotation> extractAnnotations(CtMember member)
     {
         try
@@ -454,6 +537,21 @@
         }
     }
 
+    @Override
+    public TransformField getField(String fieldName)
+    {
+        failIfFrozen();
+
+        TransformField result = fields.get(fieldName);
+
+        if (result != null)
+            return result;
+
+        throw new RuntimeException(String.format("Class %s does not contain a field named '%s'.",
+                ctClass.getName(), fieldName));
+
+    }
+
     private CtField findDeclaredCtField(String fieldName)
     {
         try
@@ -462,8 +560,7 @@
         }
         catch (NotFoundException ex)
         {
-            throw new RuntimeException(ServicesMessages.missingDeclaredField(ctClass, fieldName),
-                    ex);
+            throw new RuntimeException(ex);
         }
     }
 
@@ -559,6 +656,8 @@
 
             ctClass.addMethod(newMethod);
 
+            recordMethod(newMethod, true);
+
             TransformMethodSignature sig = getMethodSignature(newMethod);
 
             addMethodToDescription("add default", sig, "<default>");
@@ -570,6 +669,13 @@
         }
     }
 
+    private void recordMethod(CtMethod method, boolean asNew)
+    {
+        TransformMethodImpl tmi = new TransformMethodImpl(method, asNew);
+
+        methods.put(tmi.getSignature(), tmi);
+    }
+
     /**
      * Check to see if the target class (or any of its super classes) implements the provided
      * interface. This is geared
@@ -595,24 +701,7 @@
 
     public void claimField(String fieldName, Object tag)
     {
-        Defense.notBlank(fieldName, "fieldName");
-        Defense.notNull(tag, "tag");
-
-        failIfFrozen();
-
-        Object existing = claimedFields.get(fieldName);
-
-        if (existing != null)
-        {
-            String message = ServicesMessages
-                    .fieldAlreadyClaimed(fieldName, ctClass, existing, tag);
-
-            throw new RuntimeException(message);
-        }
-
-        // TODO: Ensure that fieldName is a known field?
-
-        claimedFields.put(fieldName, tag);
+        getField(fieldName).claim(tag);
     }
 
     public void addMethod(TransformMethodSignature signature, String methodBody)
@@ -667,8 +756,7 @@
 
             ctClass.addMethod(method);
 
-            if (addAsNew)
-                addedMethods.add(method);
+            recordMethod(method, addAsNew);
         }
         catch (CannotCompileException ex)
         {
@@ -719,6 +807,8 @@
             method.setExceptionTypes(exceptions);
 
             ctClass.addMethod(method);
+
+            recordMethod(method, false);
         }
         catch (CannotCompileException ex)
         {
@@ -759,7 +849,7 @@
     {
         failIfFrozen();
 
-        CtMethod method = findMethod(methodSignature);
+        CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
 
         try
         {
@@ -772,15 +862,13 @@
         }
 
         addMethodToDescription("extend", methodSignature, methodBody);
-
-        addedMethods.add(method);
     }
 
     public void extendExistingMethod(TransformMethodSignature methodSignature, String methodBody)
     {
         failIfFrozen();
 
-        CtMethod method = findMethod(methodSignature);
+        CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
 
         try
         {
@@ -803,7 +891,7 @@
         CtClass returnType = findCtClass(sourceMethod.getReturnType());
         CtClass[] parameters = buildCtClassList(sourceMethod.getParameterTypes());
         CtClass[] exceptions = buildCtClassList(sourceMethod.getExceptionTypes());
-        CtMethod source = findMethod(sourceMethod);
+        CtMethod source = findDeclaredOrSuperclassMethod(sourceMethod);
 
         try
         {
@@ -816,6 +904,8 @@
             method.setBody(source, null);
 
             ctClass.addMethod(method);
+
+            recordMethod(method, false);
         }
         catch (CannotCompileException ex)
         {
@@ -837,7 +927,7 @@
     {
         failIfFrozen();
 
-        CtMethod method = findMethod(methodSignature);
+        CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
         CtClass exceptionCtType = findCtClass(exceptionType);
 
         try
@@ -857,7 +947,7 @@
     {
         failIfFrozen();
 
-        CtMethod method = findMethod(methodSignature);
+        CtMethod method = findDeclaredOrSuperclassMethod(methodSignature);
 
         try
         {
@@ -903,7 +993,7 @@
         formatter.format("\n%s\n\n", methodBody);
     }
 
-    private CtMethod findMethod(TransformMethodSignature methodSignature)
+    private CtMethod findDeclaredOrSuperclassMethod(TransformMethodSignature methodSignature)
     {
         CtMethod method = findDeclaredMethod(methodSignature);
 
@@ -921,13 +1011,9 @@
 
     private CtMethod findDeclaredMethod(TransformMethodSignature methodSignature)
     {
-        for (CtMethod method : ctClass.getDeclaredMethods())
-        {
-            if (match(method, methodSignature))
-                return method;
-        }
+        TransformMethodImpl tmi = methods.get(methodSignature);
 
-        return null;
+        return tmi == null ? null : tmi.method;
     }
 
     private CtMethod addOverrideOfSuperclassMethod(TransformMethodSignature methodSignature)
@@ -940,12 +1026,14 @@
                 {
                     if (match(method, methodSignature))
                     {
-                        // TODO: If the moethod is not overridable (i.e. private, or final)?
+                        // TODO: 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;
                     }
                 }
@@ -1021,22 +1109,12 @@
 
         List<String> result = CollectionFactory.newList();
 
-        try
+        for (TransformFieldImpl field : fields.values())
         {
-            for (CtField field : ctClass.getDeclaredFields())
-            {
-                if (!isInstanceField(field))
-                    continue;
+            String fieldName = field.getName();
 
-                String fieldName = field.getName();
-
-                if (filter.accept(fieldName, field.getType().getName()))
-                    result.add(fieldName);
-            }
-        }
-        catch (NotFoundException ex)
-        {
-            throw new RuntimeException(ex);
+            if (filter.accept(fieldName, field.getType()))
+                result.add(fieldName);
         }
 
         Collections.sort(result);
@@ -1073,10 +1151,8 @@
 
         List<TransformMethodSignature> result = CollectionFactory.newList();
 
-        for (CtMethod method : ctClass.getDeclaredMethods())
+        for (TransformMethodSignature sig : methods.keySet())
         {
-            TransformMethodSignature sig = getMethodSignature(method);
-
             if (filter.accept(sig))
                 result.add(sig);
         }
@@ -1091,26 +1167,31 @@
         TransformMethodSignature result = methodSignatures.get(method);
         if (result == null)
         {
-            try
-            {
-                String type = method.getReturnType().getName();
-                String[] parameters = toTypeNames(method.getParameterTypes());
-                String[] exceptions = toTypeNames(method.getExceptionTypes());
+            result = toMethodSignature(method);
 
-                result = new TransformMethodSignature(method.getModifiers(), type,
-                        method.getName(), parameters, exceptions);
-
-                methodSignatures.put(method, result);
-            }
-            catch (NotFoundException ex)
-            {
-                throw new RuntimeException(ex);
-            }
+            methodSignatures.put(method, result);
         }
 
         return result;
     }
 
+    private TransformMethodSignature toMethodSignature(CtMethod method)
+    {
+        try
+        {
+            String type = method.getReturnType().getName();
+            String[] parameters = toTypeNames(method.getParameterTypes());
+            String[] exceptions = toTypeNames(method.getExceptionTypes());
+
+            return new TransformMethodSignature(method.getModifiers(), type, method.getName(),
+                    parameters, exceptions);
+        }
+        catch (NotFoundException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+
     private String[] toTypeNames(CtClass[] types)
     {
         String[] result = new String[types.length];
@@ -1127,22 +1208,14 @@
 
         List<String> names = CollectionFactory.newList();
 
-        Set<String> skipped = CollectionFactory.newSet();
-
-        skipped.addAll(claimedFields.keySet());
-        skipped.addAll(addedFieldNames);
-
-        if (removedFieldNames != null)
-            skipped.addAll(removedFieldNames);
-
-        for (CtField field : ctClass.getDeclaredFields())
+        for (TransformFieldImpl f : fields.values())
         {
-            if (!isInstanceField(field))
+            if (f.added || f.isClaimed())
                 continue;
 
-            String name = field.getName();
+            String name = f.getName();
 
-            if (skipped.contains(name))
+            if (removedFieldNames != null && removedFieldNames.contains(name))
                 continue;
 
             names.add(name);
@@ -1162,27 +1235,17 @@
 
     public String getFieldType(String fieldName)
     {
-        failIfFrozen();
-
-        CtClass type = getFieldCtType(fieldName);
-
-        return type.getName();
+        return getField(fieldName).getType();
     }
 
     public boolean isField(String fieldName)
     {
         failIfFrozen();
 
-        try
-        {
-            CtField field = ctClass.getDeclaredField(fieldName);
+        // Only declared instance fields end up in this map, and all
+        // fields are either static or private.
 
-            return isInstanceField(field);
-        }
-        catch (NotFoundException ex)
-        {
-            return false;
-        }
+        return fields.containsKey(fieldName);
     }
 
     public int getFieldModifiers(String fieldName)
@@ -1227,6 +1290,9 @@
             field.setModifiers(modifiers);
 
             ctClass.addField(field);
+
+            fields.put(fieldName, new TransformFieldImpl(field, true));
+
         }
         catch (NotFoundException ex)
         {
@@ -1239,8 +1305,6 @@
 
         formatter.format("add field: %s %s %s;\n\n", Modifier.toString(modifiers), type, fieldName);
 
-        addedFieldNames.add(fieldName);
-
         return fieldName;
     }
 
@@ -1318,8 +1382,6 @@
 
         addInjectToConstructor(fieldName, ctType, value);
 
-        addedFieldNames.add(fieldName);
-
         return fieldName;
     }
 
@@ -1521,6 +1583,8 @@
 
             ctClass.addMethod(initializerMethod);
 
+            recordMethod(initializerMethod, false);
+
             // Replace the constructor body with one that fails. This leaves, as an open question,
             // what to do about any other constructors.
 
@@ -1853,6 +1917,15 @@
 
         ExprEditor editor = new ExprEditor()
         {
+            private final Set<CtBehavior> addedMethods = CollectionFactory.newSet();
+
+            {
+                for (TransformMethodImpl tmi : methods.values())
+                {
+                    if (tmi.added)
+                        addedMethods.add(tmi.method);
+                }
+            }
 
             public void edit(FieldAccess access) throws CannotCompileException
             {
@@ -1943,7 +2016,7 @@
     {
         Defense.notNull(signature, "signature");
 
-        CtMethod method = findMethod(signature);
+        CtMethod method = findDeclaredOrSuperclassMethod(signature);
 
         int lineNumber = method.getMethodInfo2().getLineNumber(0);
         CtClass enclosingClass = method.getDeclaringClass();

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=903289&r1=903288&r2=903289&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:19 2010
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 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.
@@ -47,21 +47,11 @@
         return MESSAGES.get("markup-writer-no-current-element");
     }
 
-    static String missingDeclaredField(CtClass ctClass, String fieldName)
-    {
-        return MESSAGES.format("missing-declared-field", ctClass.getName(), fieldName);
-    }
-
     static String errorAddingMethod(CtClass ctClass, String methodName, Throwable cause)
     {
         return MESSAGES.format("error-adding-method", ctClass.getName(), methodName, cause);
     }
 
-    static String fieldAlreadyClaimed(String fieldName, CtClass ctClass, Object existingTag, Object newTag)
-    {
-        return MESSAGES.format("field-already-claimed", fieldName, ctClass.getName(), existingTag, newTag);
-    }
-
     static String noDeclaredMethod(CtClass ctClass, TransformMethodSignature methodSignature)
     {
         return MESSAGES.format("no-declared-method", ctClass.getName(), methodSignature);

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=903289&r1=903288&r2=903289&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:19 2010
@@ -33,22 +33,21 @@
  * naming conventions. Most of the changes are provided by different implementations of
  * {@link ComponentClassTransformWorker}.
  * <p/>
- * Much of this information is somewhat like ordinary reflection, but applies to a class that has
- * not yet been loaded.
+ * Much of this information is somewhat like ordinary reflection, but applies to a class that has not yet been loaded.
  * <p/>
- * Transformation is primarily about identifying annotations on fields and on methods and changing
- * the class, adding new interfaces, fields and methods, and deleting some existing fields.
+ * Transformation is primarily about identifying annotations on fields and on methods and changing the class, adding new
+ * interfaces, fields and methods, and deleting some existing fields.
  * <p/>
- * A ClassTransformation contains all the state data specific to a particular class being
- * transformed. A number of <em>workers</em> will operate upon the ClassTransformation to effect the
- * desired changes before the true class is loaded into memory.
+ * A ClassTransformation contains all the state data specific to a particular class being transformed. A number of
+ * <em>workers</em> will operate upon the ClassTransformation to effect the desired changes before the true class is
+ * loaded into memory.
  * <p/>
- * Instances of this class are not designed to be thread safe, access to an instance should be
- * restricted to a single thread. In fact, the design of this type is to allow stateless singletons
- * in multiple threads to work on thread-specific data (within the ClassTransformation).
+ * Instances of this class are not designed to be thread safe, access to an instance should be restricted to a single
+ * thread. In fact, the design of this type is to allow stateless singletons in multiple threads to work on
+ * thread-specific data (within the ClassTransformation).
  * <p/>
- * The majority of methods concern the <em>declared</em> members (field and methods) of a specific
- * class, rather than any fields or methods inherited from a base class.
+ * The majority of methods concern the <em>declared</em> members (field and methods) of a specific class, rather than
+ * any fields or methods inherited from a base class.
  * 
  * @see org.apache.tapestry5.services.TapestryModule#contributeComponentClassTransformWorker(org.apache.tapestry5.ioc.OrderedConfiguration,
  *      org.apache.tapestry5.ioc.ObjectLocator, InjectionProvider, ComponentClassResolver)
@@ -134,10 +133,23 @@
      * @return the annotation if present, or null otherwise
      * @throws IllegalArgumentException
      *             if the fieldName does not correspond to a declared field
+     * @deprecated Use {@link TransformField#getAnnotation(Class)} instead
      */
     <T extends Annotation> T getFieldAnnotation(String fieldName, Class<T> annotationClass);
 
     /**
+     * Locates a declared field by its field name. The field must exist.
+     * 
+     * @param name
+     *            of declared field
+     * @return field information
+     * @throws RuntimeException
+     *             if no such field
+     * @since 5.2.0
+     */
+    TransformField getField(String fieldName);
+
+    /**
      * Finds an annotation on a declared method.
      * 
      * @param <T>
@@ -185,8 +197,7 @@
     void makeReadOnly(String fieldName);
 
     /**
-     * Finds any declared <em>instance</em> fields that have not been claimed (via
-     * {@link #claimField(String, Object)})
+     * Finds any declared <em>instance</em> fields that have not been claimed (via {@link #claimField(String, Object)})
      * and returns the names of those fields. May return an empty array.
      */
     List<String> findUnclaimedFields();
@@ -196,8 +207,9 @@
      * 
      * @param fieldName
      * @return the type of the field, as a string
-     * @throws IllegalArgumentException
+     * @throws RuntimeException
      *             if the fieldName does not correspond to a declared instance field
+     * @deprecated Use {@link TransformField#getType()} instead
      */
     String getFieldType(String fieldName);
 
@@ -300,8 +312,8 @@
      * methods of the interface
      * are added.
      * <p/>
-     * TODO: Checking that the names of methods in the interface do not conflict with the names of
-     * methods present in the (unmodified) class.
+     * TODO: Checking that the names of methods in the interface do not conflict with the names of methods present in
+     * the (unmodified) class.
      * 
      * @param interfaceClass
      *            the interface to be implemented by the class
@@ -315,15 +327,14 @@
      * 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. Use
-     * {@link #addMethod(TransformMethodSignature, String)} when it is necessary to control when the
-     * super-class method is invoked.
+     * 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. Use
+     * {@link #addMethod(TransformMethodSignature, String)} when it is necessary to control when the super-class method
+     * is invoked.
      * <p/>
      * The extended method is considered <em>new</em>. New methods <em>are not</em> scanned for
-     * {@linkplain #removeField(String)} removed}, {@linkplain #replaceReadAccess(String, String)}
-     * read replaced}, or {@linkplain #replaceWriteAccess(String, String) write replaced} fields.
-     * Generally that's what you want!
+     * {@linkplain #removeField(String)} removed}, {@linkplain #replaceReadAccess(String, String)} read replaced}, or
+     * {@linkplain #replaceWriteAccess(String, String) write replaced} fields. Generally that's what you want!
      * 
      * @param methodSignature
      *            the signature of the method to extend
@@ -353,15 +364,13 @@
     /**
      * Inserts code at the beginning of a method body (i.e. {@link CtBehavior#insertBefore(String)}.
      * <p/>
-     * The method may be declared in the class, or may be inherited from a super-class. For
-     * inherited methods, a method is added that first invokes the super implementation. Use
-     * {@link #addMethod(TransformMethodSignature, String)} when it is necessary to control when the
-     * super-class method is invoked.
+     * The method may be declared in the class, or may be inherited from a super-class. For inherited methods, a method
+     * is added that first invokes the super implementation. Use {@link #addMethod(TransformMethodSignature, String)}
+     * when it is necessary to control when the super-class method is invoked.
      * <p/>
      * <p/>
-     * Like {@link #extendExistingMethod(TransformMethodSignature, String)}, this method is
-     * generally used to "wrap" an existing method adding additional functionality such as caching
-     * or transaction support.
+     * Like {@link #extendExistingMethod(TransformMethodSignature, String)}, this method is generally used to "wrap" an
+     * existing method adding additional functionality such as caching or transaction support.
      * 
      * @param methodSignature
      * @param methodBody
@@ -371,8 +380,7 @@
     void prefixMethod(TransformMethodSignature methodSignature, String methodBody);
 
     /**
-     * Returns the name of a field that provides the {@link org.apache.tapestry5.ComponentResources}
-     * for the transformed
+     * Returns the name of a field that provides the {@link org.apache.tapestry5.ComponentResources} for the transformed
      * component. This will be a protected field, accessible to the class and subclasses.
      * 
      * @return name of field

Added: 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=903289&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java Tue Jan 26 16:02:19 2010
@@ -0,0 +1,59 @@
+// Copyright 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services;
+
+import org.apache.tapestry5.ioc.AnnotationProvider;
+
+/**
+ * A field defined by (or created within) a {@link ClassTransformation},
+ * allowing the details of the field to be
+ * accessed or modified.
+ * 
+ * @since 5.2.0
+ */
+public interface TransformField extends AnnotationProvider
+{
+    /**
+     * Returns the name of the field.
+     */
+    String getName();
+
+    /**
+     * Returns the field's type, either a primitive name
+     * or a fully qualified class name, or an array type name
+     * (in Java source syntax).
+     */
+    String getType();
+
+    /**
+     * True if the field is a primitive type, not an object type.
+     * Array types are object types.
+     */
+    boolean isPrimitive();
+
+    /**
+     * Claims the field so as to ensure that only a single annotation is applied to any single field.
+     * When a transformation occurs (driven by a field annotation), the field is claimed (using the
+     * annotation object as the tag). If a field has multiple conflicting annotations, this will be discovered when
+     * the code attempts to claim the field a second time.
+     * 
+     * @param tag
+     *            a non-null object that represents why the field is being tagged (this is typically
+     *            a specific annotation on the field)
+     * @throws IllegalStateException
+     *             if the field is already claimed for some other tag
+     */
+    void claim(Object tag);
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformField.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 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=903289&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java Tue Jan 26 16:02:19 2010
@@ -0,0 +1,32 @@
+// Copyright 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services;
+
+import org.apache.tapestry5.ioc.AnnotationProvider;
+
+/**
+ * A method defined by (or created within) a {@link ClassTransformation}, allowing
+ * for access and manipulation of the method.
+ * 
+ * @since 5.2.0
+ */
+public interface TransformMethod extends AnnotationProvider
+{
+    /**
+     * @return the signature for the method, defining name, visibility, return type, parameter types and thrown
+     *         exceptions
+     */
+    TransformMethodSignature getSignature();
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TransformMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=903289&r1=903288&r2=903289&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:19 2010
@@ -1,4 +1,4 @@
-# Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+# Copyright 2006, 2007, 2008, 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.
@@ -16,9 +16,7 @@
 markup-writer-no-current-element=This markup writer does not have a current element. \
   The current element is established with the first call to element() and is \
   maintained across subsequent calls. 
-missing-declared-field=Class %s does not contain a field named '%s'.
 error-adding-method=Error adding method %s to class %s: %s 
-field-already-claimed=Field %s of class %s is already claimed by %s and can not be claimed by %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.