org.apache.tapestry5.internal.services
Class InternalClassTransformationImpl

java.lang.Object
  extended by org.apache.tapestry5.internal.services.InternalClassTransformationImpl
All Implemented Interfaces:
InternalClassTransformation, AnnotationProvider, ClassTransformation

public final class InternalClassTransformationImpl
extends Object
implements InternalClassTransformation

Implementation of the InternalClassTransformation interface.


Constructor Summary
InternalClassTransformationImpl(ClassFactory classFactory, javassist.CtClass ctClass, ComponentClassCache componentClassCache, ComponentModel componentModel, CtClassSource classSource)
          This is a constructor for a base class.
 
Method Summary
 void addCatch(TransformMethodSignature methodSignature, String exceptionType, String body)
          Adds a catch block to the method.
 String addField(int modifiers, String type, String suggestedName)
          Defines a new declared field for the class.
 void addImplementedInterface(Class interfaceClass)
          Transforms the class to implement the indicated interface.
 String addInjectedField(Class type, String suggestedName, Object value)
          Defines a new protected instance variable whose initial value is provided statically, via a constructor parameter.
 void addMethod(TransformMethodSignature signature, String methodBody)
          Adds a new method to the transformed class.
 void addTransformedMethod(TransformMethodSignature signature, String methodBody)
          As with ClassTransformation.addMethod(TransformMethodSignature, String), but field references inside the method will be transformed, and the method must not already exist.
 void advise(TransformMethodSignature methodSignature, ComponentMethodAdvice advice)
          Adds method advice for the indicated method.
 void claimField(String fieldName, Object tag)
          Claims a field so as to ensure that only a single annotation is applied to any single field.
 void copyMethod(TransformMethodSignature sourceMethod, int modifiers, String newMethodName)
          Creates a new method by copying the body of an existing method.
 InternalClassTransformation createChildTransformation(javassist.CtClass childClass, MutableComponentModel childModel)
           
 Instantiator createInstantiator()
          Called (after InternalClassTransformation.finish()) to construct an instantiator for the component.
 void extendConstructor(String statement)
          Adds a statement to the constructor.
 void extendExistingMethod(TransformMethodSignature methodSignature, String methodBody)
          Like ClassTransformation.extendMethod(TransformMethodSignature, String), but the extension does not mark the method as new, and field changes will be processed.
 void extendMethod(TransformMethodSignature methodSignature, String methodBody)
          Extends an existing method.
 List<String> findFields(FieldFilter filter)
          Finds all unclaimed fields matched by the provided filter.
 List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass)
          Generates a list of the names of declared instance fields that have the indicated annotation.
 List<TransformMethodSignature> findMethods(MethodFilter filter)
          Finds all methods matched by the provided filter.
 List<TransformMethodSignature> findMethodsWithAnnotation(Class<? extends Annotation> annotationClass)
          Finds all methods defined in the class that are marked with the provided annotation.
 List<String> findUnclaimedFields()
          Finds any declared instance fields that have not been claimed (via ClassTransformation.claimField(String, Object)) and returns the names of those fields.
 void finish()
          Invoked after all ComponentClassTransformWorkers have had their chance to work over the class.
<T extends Annotation>
T
getAnnotation(Class<T> annotationClass)
          Searches for the specified annotation, returning the matching annotation instance.
 List<Annotation> getClassAnnotations()
           
 String getClassName()
          Returns the fully qualified class name of the class being transformed.
 List<ConstructorArg> getConstructorArgs()
          Returns a copy of the list of constructor arguments for this class.
<T extends Annotation>
T
getFieldAnnotation(String fieldName, Class<T> annotationClass)
          Finds an annotation on a declared instance field.
 int getFieldModifiers(String fieldName)
          Returns the modifiers for the named field.
 String getFieldType(String fieldName)
          Obtains the type of a declared instance field.
 IdAllocator getIdAllocator()
          Returns a copy of the transformation's IdAllocator.
 org.slf4j.Logger getLogger()
          Returns a logger, based on the class name being transformed, to which warnings or errors concerning the class being transformed may be logged.
<T extends Annotation>
T
getMethodAnnotation(TransformMethodSignature signature, Class<T> annotationClass)
          Finds an annotation on a declared method.
 String getMethodIdentifier(TransformMethodSignature signature)
          Converts a signature to a string used to identify the method; this consists of the TransformMethodSignature.getMediumDescription() appended with source file information and line number information (when available).
 InternalClassTransformation getParentTransformation()
          Returns the parent transformation, or null for a root class.
 String getResourcesFieldName()
          Returns the name of a field that provides the ComponentResources for the transformed component.
 void injectField(String fieldName, Object value)
          Converts the field into a read only field whose value is the provided value.
 boolean isField(String fieldName)
          Returns true if the indicated name is a private instance field.
 boolean isMethod(TransformMethodSignature signature)
          Returns true if the provided signature is a method implemented by the transformed class.
 boolean isMethodOverride(TransformMethodSignature methodSignature)
          Returns true if the method is an override of a method from the parent class.
 boolean isRootTransformation()
          Returns true if this transformation represents a root class (one that extends directly from Object), or false if this transformation is an extension of another transformed class.
 void makeReadOnly(String fieldName)
          Changes the field to be read only.
 String newMemberName(String suggested)
          Returns the name of a new member (field or method).
 String newMemberName(String prefix, String baseName)
          As with ClassTransformation.newMemberName(String), but the suggested name is constructed from the prefix and base name.
 void prefixMethod(TransformMethodSignature methodSignature, String methodBody)
          Inserts code at the beginning of a method body (i.e.
 void removeField(String fieldName)
          Removes a field entirely; this is useful for fields that are replaced entirely by computed values.
 void replaceReadAccess(String fieldName, String methodName)
          Replaces all read-references to the specified field with invocations of the specified method name.
 void replaceWriteAccess(String fieldName, String methodName)
          Replaces all write accesses to the specified field with invocations of the specified method name.
 String searchForPreviousInjection(InjectionKey key)
          Searchs for an existing injection of an object, returning the name of the protected field into which the value was injected.
 Class toClass(String type)
          Converts a type name into a corresponding class (possibly, a transformed class).
 String toString()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

InternalClassTransformationImpl

public InternalClassTransformationImpl(ClassFactory classFactory,
                                       javassist.CtClass ctClass,
                                       ComponentClassCache componentClassCache,
                                       ComponentModel componentModel,
                                       CtClassSource classSource)
This is a constructor for a base class.

Method Detail

createChildTransformation

public InternalClassTransformation createChildTransformation(javassist.CtClass childClass,
                                                             MutableComponentModel childModel)
Specified by:
createChildTransformation in interface InternalClassTransformation

getResourcesFieldName

public String getResourcesFieldName()
Description copied from interface: ClassTransformation
Returns the name of a field that provides the ComponentResources for the transformed component. This will be a protected field, accessible to the class and subclasses.

Specified by:
getResourcesFieldName in interface ClassTransformation
Returns:
name of field

getFieldAnnotation

public <T extends Annotation> T getFieldAnnotation(String fieldName,
                                                   Class<T> annotationClass)
Description copied from interface: ClassTransformation
Finds an annotation on a declared instance field.

Specified by:
getFieldAnnotation in interface ClassTransformation
Type Parameters:
T - constrains parameter and return value to Annotation types
Parameters:
fieldName - the name of the field, which must exist
annotationClass - the type of annotation to access
Returns:
the annotation if present, or null otherwise

getMethodAnnotation

public <T extends Annotation> T getMethodAnnotation(TransformMethodSignature signature,
                                                    Class<T> annotationClass)
Description copied from interface: ClassTransformation
Finds an annotation on a declared method.

Specified by:
getMethodAnnotation in interface ClassTransformation
Type Parameters:
T - constrains parameter and return value to Annotation types
Parameters:
signature - the method signature to search
annotationClass - the type of annotation to access
Returns:
the annotation if present, or null otherwise

getAnnotation

public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
Description copied from interface: AnnotationProvider
Searches for the specified annotation, returning the matching annotation instance.

Specified by:
getAnnotation in interface AnnotationProvider
Parameters:
annotationClass - used to select the annotation to return�
Returns:
the annotation, or null if not found

newMemberName

public String newMemberName(String suggested)
Description copied from interface: ClassTransformation
Returns the name of a new member (field or method). Ensures that the resulting name does not conflict with any existing member (declared by the underlying class, or inherited from a base class).

Specified by:
newMemberName in interface ClassTransformation
Parameters:
suggested - the suggested value for the member
Returns:
a unique name for the member

newMemberName

public String newMemberName(String prefix,
                            String baseName)
Description copied from interface: ClassTransformation
As with ClassTransformation.newMemberName(String), but the suggested name is constructed from the prefix and base name. An underscore will seperate the prefix from the base name.

Specified by:
newMemberName in interface ClassTransformation
Parameters:
prefix - for the generated name
baseName - an name, often of an existing field or method
Returns:
a unique name

addImplementedInterface

public void addImplementedInterface(Class interfaceClass)
Description copied from interface: ClassTransformation
Transforms the class to implement the indicated interface. If the class (or its super class) does not already implement the interface, then the interface is added, and default implementations of any methods of the interface are added.

TODO: Checking that the names of methods in the interface do not conflict with the names of methods present in the (unmodified) class.

Specified by:
addImplementedInterface in interface ClassTransformation
Parameters:
interfaceClass - the interface to be implemented by the class

claimField

public void claimField(String fieldName,
                       Object tag)
Description copied from interface: ClassTransformation
Claims a 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.

Specified by:
claimField in interface ClassTransformation
Parameters:
fieldName - the name of the field that is being claimed
tag - a non-null object that represents why the field is being tagged (this is typically a specific annotation on the field)

addMethod

public void addMethod(TransformMethodSignature signature,
                      String methodBody)
Description copied from interface: ClassTransformation
Adds a new method to the transformed class. Replaces any existing method declared for the class. When overriding a super-class method, you should use ClassTransformation.extendMethod(TransformMethodSignature, String), or you should remember to invoke the super class implemetation explicitly. Use this method to control when the super-class implementation is invoked.

Specified by:
addMethod in interface ClassTransformation

addTransformedMethod

public void addTransformedMethod(TransformMethodSignature signature,
                                 String methodBody)
Description copied from interface: ClassTransformation
As with ClassTransformation.addMethod(TransformMethodSignature, String), but field references inside the method will be transformed, and the method must not already exist.

Specified by:
addTransformedMethod in interface ClassTransformation

extendMethod

public void extendMethod(TransformMethodSignature methodSignature,
                         String methodBody)
Description copied from interface: ClassTransformation
Extends an existing method. The provided method body is inserted at the end of the existing method (i.e. CtBehavior.insertAfter(java.lang.String)). To access or change the return value, use the $_ pseudo variable.

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 ClassTransformation.addMethod(TransformMethodSignature, String) when it is necessary to control when the super-class method is invoked.

The extended method is considered new. New methods are not scanned for ClassTransformation.removeField(String) removed}, ClassTransformation.replaceReadAccess(String, String) read replaced}, or write replaced fields. Generally that's what you want!

Specified by:
extendMethod in interface ClassTransformation
Parameters:
methodSignature - the signature of the method to extend
methodBody - the body of code
See Also:
ClassTransformation.extendExistingMethod(TransformMethodSignature, String)

extendExistingMethod

public void extendExistingMethod(TransformMethodSignature methodSignature,
                                 String methodBody)
Description copied from interface: ClassTransformation
Like ClassTransformation.extendMethod(TransformMethodSignature, String), but the extension does not mark the method as new, and field changes will be processed.

Specified by:
extendExistingMethod in interface ClassTransformation
Parameters:
methodSignature - signature of the method to extend
methodBody - the body of code
See Also:
ClassTransformation.prefixMethod(TransformMethodSignature, String)

copyMethod

public void copyMethod(TransformMethodSignature sourceMethod,
                       int modifiers,
                       String newMethodName)
Description copied from interface: InternalClassTransformation
Creates a new method by copying the body of an existing method. This is part of the scheme for providing method advice.

Specified by:
copyMethod in interface InternalClassTransformation
Parameters:
sourceMethod - method to be copied
modifiers - modifiers for the new method
newMethodName - name of new method to create

addCatch

public void addCatch(TransformMethodSignature methodSignature,
                     String exceptionType,
                     String body)
Description copied from interface: ClassTransformation
Adds a catch block to the method. The body should end with a return or a throw. The special Javassist variable $e is the exception instance.

Specified by:
addCatch in interface ClassTransformation
Parameters:
methodSignature - method to be extended.
exceptionType - fully qualified class name of exception
body - code to execute

prefixMethod

public void prefixMethod(TransformMethodSignature methodSignature,
                         String methodBody)
Description copied from interface: ClassTransformation
Inserts code at the beginning of a method body (i.e. CtBehavior.insertBefore(String).

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 ClassTransformation.addMethod(TransformMethodSignature, String) when it is necessary to control when the super-class method is invoked.

Like ClassTransformation.extendExistingMethod(TransformMethodSignature, String), this method is generally used to "wrap" an existing method adding additional functionality such as caching or transaction support.

Specified by:
prefixMethod in interface ClassTransformation

findFieldsWithAnnotation

public List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass)
Description copied from interface: ClassTransformation
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.

Specified by:
findFieldsWithAnnotation in interface ClassTransformation

findFields

public List<String> findFields(FieldFilter filter)
Description copied from interface: ClassTransformation
Finds all unclaimed fields matched by the provided filter. Only considers private instance fields.

Specified by:
findFields in interface ClassTransformation
Parameters:
filter - passed each field name and field type
Returns:
the names of all matched fields, in ascending order

findMethodsWithAnnotation

public List<TransformMethodSignature> findMethodsWithAnnotation(Class<? extends Annotation> annotationClass)
Description copied from interface: ClassTransformation
Finds all methods defined in the class that are marked with the provided annotation.

Specified by:
findMethodsWithAnnotation in interface ClassTransformation
Returns:
a list of method signature (which may be empty) in ascending order
See Also:
ClassTransformation.findMethods(MethodFilter)

findMethods

public List<TransformMethodSignature> findMethods(MethodFilter filter)
Description copied from interface: ClassTransformation
Finds all methods matched by the provided filter.

Specified by:
findMethods in interface ClassTransformation
Parameters:
filter - Passed each method signature, it may include or exclude each potential
Returns:
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.

findUnclaimedFields

public List<String> findUnclaimedFields()
Description copied from interface: ClassTransformation
Finds any declared instance fields that have not been claimed (via ClassTransformation.claimField(String, Object)) and returns the names of those fields. May return an empty array.

Specified by:
findUnclaimedFields in interface ClassTransformation

getFieldType

public String getFieldType(String fieldName)
Description copied from interface: ClassTransformation
Obtains the type of a declared instance field.

Specified by:
getFieldType in interface ClassTransformation
Returns:
the type of the field, as a string

isField

public boolean isField(String fieldName)
Description copied from interface: ClassTransformation
Returns true if the indicated name is a private instance field.

Specified by:
isField in interface ClassTransformation
Returns:
true if field exists

getFieldModifiers

public int getFieldModifiers(String fieldName)
Description copied from interface: ClassTransformation
Returns the modifiers for the named field.

Specified by:
getFieldModifiers in interface ClassTransformation

addField

public String addField(int modifiers,
                       String type,
                       String suggestedName)
Description copied from interface: ClassTransformation
Defines a new declared field for the class. The suggestedName may be modified to ensure uniqueness.

Specified by:
addField in interface ClassTransformation
Parameters:
modifiers - modifiers for the field (typically, Modifier.PRIVATE)
type - the type for the field, as a string
suggestedName - the desired name for the field, which may be modified (for uniqueness) when returned
Returns:
the (uniqued) name for the field

addInjectedField

public String addInjectedField(Class type,
                               String suggestedName,
                               Object value)
Description copied from interface: ClassTransformation
Defines a new protected instance variable whose initial value is provided statically, via a constructor parameter. The transformation caches the result, so calling this method repeatedly with the same type and value will return the same field name. Caching extends to the parent transformation, so that a value injected into a parent class will be available (via the protected instance variable) to subclasses.

Specified by:
addInjectedField in interface ClassTransformation
Parameters:
type - the type of object to inject
suggestedName - the suggested name for the new field
value - to be injected. This value is retained.
Returns:
the actual name of the injected field

searchForPreviousInjection

public String searchForPreviousInjection(InjectionKey key)
Description copied from interface: InternalClassTransformation
Searchs for an existing injection of an object, returning the name of the protected field into which the value was injected.

TODO: Howard sayz: Uggh! At least define a real key (MultiKey is intended for internal use, never part of an API). Is this necessary? The cost of re-injection is tiny.

Specified by:
searchForPreviousInjection in interface InternalClassTransformation

advise

public void advise(TransformMethodSignature methodSignature,
                   ComponentMethodAdvice advice)
Description copied from interface: ClassTransformation
Adds method advice for the indicated method.

Specified by:
advise in interface ClassTransformation

isMethodOverride

public boolean isMethodOverride(TransformMethodSignature methodSignature)
Description copied from interface: ClassTransformation
Returns true if the method is an override of a method from the parent class.

Specified by:
isMethodOverride in interface ClassTransformation
Parameters:
methodSignature - signature of method to check
Returns:
true if the parent class contains a method with the name signature

getParentTransformation

public InternalClassTransformation getParentTransformation()
Description copied from interface: InternalClassTransformation
Returns the parent transformation, or null for a root class.

Specified by:
getParentTransformation in interface InternalClassTransformation

isMethod

public boolean isMethod(TransformMethodSignature signature)
Description copied from interface: InternalClassTransformation
Returns true if the provided signature is a method implemented by the transformed class.

Specified by:
isMethod in interface InternalClassTransformation
Returns:
true if implemented

injectField

public void injectField(String fieldName,
                        Object value)
Description copied from interface: ClassTransformation
Converts the field into a read only field whose value is the provided value. This is used when converting an existing field into a read-only injected value.

Specified by:
injectField in interface ClassTransformation
Parameters:
fieldName - name of field to convert
value - the value provided by the field

finish

public void finish()
Description copied from interface: InternalClassTransformation
Invoked after all ComponentClassTransformWorkers have had their chance to work over the class. This performs any final operations for the class transformation, which includes coming up with the final constructor method for the class.

Specified by:
finish in interface InternalClassTransformation

createInstantiator

public Instantiator createInstantiator()
Description copied from interface: InternalClassTransformation
Called (after InternalClassTransformation.finish()) to construct an instantiator for the component.

Specified by:
createInstantiator in interface InternalClassTransformation
Returns:
the component's instantiator

getIdAllocator

public IdAllocator getIdAllocator()
Description copied from interface: InternalClassTransformation
Returns a copy of the transformation's IdAllocator. Used when creating a child class transformation. May only be invoked on a frozen transformation.

Specified by:
getIdAllocator in interface InternalClassTransformation

getConstructorArgs

public List<ConstructorArg> getConstructorArgs()
Description copied from interface: InternalClassTransformation
Returns a copy of the list of constructor arguments for this class.

Specified by:
getConstructorArgs in interface InternalClassTransformation

getClassAnnotations

public List<Annotation> getClassAnnotations()

toString

public String toString()
Overrides:
toString in class Object

makeReadOnly

public void makeReadOnly(String fieldName)
Description copied from interface: ClassTransformation
Changes the field to be read only. Any existing code that changes the field will cause a runtime exception.

Specified by:
makeReadOnly in interface ClassTransformation
Parameters:
fieldName - name of field to so change

removeField

public void removeField(String fieldName)
Description copied from interface: ClassTransformation
Removes a field entirely; this is useful for fields that are replaced entirely by computed values.

Specified by:
removeField in interface ClassTransformation
Parameters:
fieldName - the name of the field to remove
See Also:
ClassTransformation.replaceReadAccess(String, String), ClassTransformation.replaceWriteAccess(String, String)

replaceReadAccess

public void replaceReadAccess(String fieldName,
                              String methodName)
Description copied from interface: ClassTransformation
Replaces all read-references to the specified field with invocations of the specified method name. Replacements do not occur in methods added via ClassTransformation.addMethod(TransformMethodSignature, String) or ClassTransformation.extendMethod(TransformMethodSignature, String).

Specified by:
replaceReadAccess in interface ClassTransformation

replaceWriteAccess

public void replaceWriteAccess(String fieldName,
                               String methodName)
Description copied from interface: ClassTransformation
Replaces all write accesses to the specified field with invocations of the specified method name. The method should take a single parameter of the same type as the field. Replacements do not occur in methods added via ClassTransformation.addMethod(TransformMethodSignature, String) or ClassTransformation.extendMethod(TransformMethodSignature, String).

Specified by:
replaceWriteAccess in interface ClassTransformation

toClass

public Class toClass(String type)
Description copied from interface: ClassTransformation
Converts a type name into a corresponding class (possibly, a transformed class). Primitive type names are returned as wrapper types.

Specified by:
toClass in interface ClassTransformation

getClassName

public String getClassName()
Description copied from interface: ClassTransformation
Returns the fully qualified class name of the class being transformed.

Specified by:
getClassName in interface ClassTransformation

getLogger

public org.slf4j.Logger getLogger()
Description copied from interface: ClassTransformation
Returns a logger, based on the class name being transformed, to which warnings or errors concerning the class being transformed may be logged.

Specified by:
getLogger in interface ClassTransformation

extendConstructor

public void extendConstructor(String statement)
Description copied from interface: ClassTransformation
Adds a statement to the constructor. The statement is added as is, though a newline is added.

Specified by:
extendConstructor in interface ClassTransformation
Parameters:
statement - the statement to add, which should end with a semicolon

getMethodIdentifier

public String getMethodIdentifier(TransformMethodSignature signature)
Description copied from interface: ClassTransformation
Converts a signature to a string used to identify the method; this consists of the TransformMethodSignature.getMediumDescription() appended with source file information and line number information (when available).

Specified by:
getMethodIdentifier in interface ClassTransformation
Returns:
a string that identifies the class, method name, types of parameters, source file and source line number

isRootTransformation

public boolean isRootTransformation()
Description copied from interface: ClassTransformation
Returns true if this transformation represents a root class (one that extends directly from Object), or false if this transformation is an extension of another transformed class.

Specified by:
isRootTransformation in interface ClassTransformation
Returns:
true if root class, false if sub-class


Copyright © 2006-2009 Apache Software Foundation. All Rights Reserved.