001 // Copyright 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.plastic; 016 017 import java.lang.annotation.Annotation; 018 import java.lang.reflect.Method; 019 import java.util.List; 020 import java.util.Set; 021 022 /** 023 * The representation of a class while it is being instrumented and transformed. PlasticClass allows 024 * for an imperative style of development: the PlasticClass is provided to other objects; they can query it 025 * for relevant fields or methods, and invoke methods that modify the class in various ways. Ultimately, the 026 * end result is a {@link ClassInstantiator} used to create instances of the fully instrumented and transformed class. 027 * <p/> 028 * The terminology is that a class that is being transformed is "plastic", but the end result is a normal concrete class 029 * (albeit in a different class loader). 030 * <p/> 031 * Implements {@link AnnotationAccess} to provide access to annotations on the type itself. 032 * <p/> 033 * This class is expressly <em>not thread safe</em>; only a single thread should be responsible for operating on a 034 * PlasticClass. 035 * <p/> 036 * TODO: what about annotation inheritance? 037 */ 038 @SuppressWarnings("rawtypes") 039 public interface PlasticClass extends AnnotationAccess 040 { 041 /** 042 * Returns the fully qualified class name of the class being transformed. 043 */ 044 String getClassName(); 045 046 /** 047 * Matches all fields (claimed or not) that have the given annotation. Returns the fields in sorted order. 048 * 049 * @return Unmodifiable List of fields. 050 */ 051 <T extends Annotation> List<PlasticField> getFieldsWithAnnotation(Class<T> annotationType); 052 053 /** 054 * Returns all non-introduced fields, in sorted order by name. 055 * 056 * @return Unmodifiable list of fields. 057 */ 058 List<PlasticField> getAllFields(); 059 060 /** 061 * Returns all unclaimed fields, in sorted order by name. This does not include introduced fields. 062 * 063 * @return Unmodifiable list of fields. 064 * @see PlasticField#claim(Object) 065 */ 066 List<PlasticField> getUnclaimedFields(); 067 068 /** 069 * Introduces a new private field into the class. 070 * 071 * @param typeName the Java class name for the field, or (possibly) a primitive type name or an array 072 * @param suggestedName the suggested name for the field, which may be modified to ensure that the field name 073 * is unique 074 * @return PlasticField for the introduced field 075 */ 076 PlasticField introduceField(String typeName, String suggestedName); 077 078 /** 079 * Convenience method that uses a Java class rather than a type name. 080 */ 081 PlasticField introduceField(Class fieldType, String suggestedName); 082 083 /** 084 * Introduces a new private method into the class, ensuring that the method name is unique. 085 * 086 * @param typeName return type of method 087 * @param suggestedName suggested name for the method; the actual method name may be modified to ensure uniqueness 088 * @param argumentTypes types of any arguments (may be null) 089 * @param exceptionTypes type of any checked exceptions (may be null) 090 * @return new method, with default implementation 091 */ 092 PlasticMethod introducePrivateMethod(String typeName, String suggestedName, String[] argumentTypes, 093 String[] exceptionTypes); 094 095 /** 096 * Matches methods with the given annotation. 097 * 098 * @return Unmodifiable list of methods, in sorted order. 099 */ 100 <T extends Annotation> List<PlasticMethod> getMethodsWithAnnotation(Class<T> annotationType); 101 102 /** 103 * Returns all methods of the class, in sorted order. This does not include static methods, 104 * or any {@linkplain #introduceMethod(MethodDescription) introduced methods}. 105 * 106 * @return Unmodifiable list of methods. 107 */ 108 List<PlasticMethod> getMethods(); 109 110 /** 111 * Returns an existing method declared in this class, or introduces a new method into this class. 112 * The method is created with default behavior. If the method overrides a non-private, non-abstract method 113 * implemented in a <em>transformed</em> super class, the the default behavior is to invoke that method and return 114 * its value. Otherwise, the default behavior is to ignore parameters and return 0, false, or null. Void methods 115 * will invoke the super-class implementation (if it exists) and return no value. 116 * <p/> 117 * It is allowed for the method description to indicate an abstract method; however the abstract flag will be 118 * removed, and a non-abstract method will be created. 119 * 120 * @param description describes the method name, visibility, return value, etc. 121 * @return a new (or previously created) PlasticMethod for the method 122 * @throws IllegalArgumentException if the method is abstract or static 123 */ 124 PlasticMethod introduceMethod(MethodDescription description); 125 126 /** 127 * Returns an existing method declared in this class, or introduces a new method into this class. 128 * The method is created with default behavior. 129 * <p/> 130 * It is allowed for the method description to indicate an abstract method; however the abstract flag will be 131 * removed, and a non-abstract method will be created. 132 * 133 * @param description describes the method name, visibility, return value, etc. 134 * @param callback used to create the implementation of the method 135 * @return a new (or previously created) PlasticMethod for the method 136 * @throws IllegalArgumentException if the method is abstract or static 137 */ 138 PlasticMethod introduceMethod(MethodDescription description, InstructionBuilderCallback callback); 139 140 /** 141 * A convenience that creates a {@link MethodDescription} from the Method and introduces that. This is often 142 * invoked when walking the methods of an interface and introducing each of those methods. 143 * <p/> 144 * Introduced methods are always concrete, not abstract. The abstract flag on the method modifiers will always be 145 * stripped off, which is handy when {@linkplain #introduceInterface(Class) introducing methods from an interface}. 146 * 147 * @param method to introduce 148 * @return new (or previously created) PlasticMethod 149 */ 150 PlasticMethod introduceMethod(Method method); 151 152 /** 153 * Introduces each method defined by the interface into the class. Determines which new methods must 154 * be introduced in order to ensure that all methods of the interface are implemented. The newly introduced methods, 155 * if any, are returned. 156 */ 157 Set<PlasticMethod> introduceInterface(Class interfaceType); 158 159 /** 160 * Introduces the interface, and then invokes {@link PlasticMethod#delegateTo(PlasticField)} on each method 161 * defined by the interface. 162 * 163 * @param interfaceType defines the interface to proxy 164 * @param field field containing an object to delegate to 165 * @return this plastic class, for further configuration 166 */ 167 PlasticClass proxyInterface(Class interfaceType, PlasticField field); 168 169 /** 170 * Conditionally adds an implementation of <code>toString()</code> to the class, but only if it is not already 171 * present in the class, or in a (transformed) super-class. 172 * 173 * @param toStringValue the fixed value to be returned from invoking toString() 174 * @return this plastic class, for further configuration 175 */ 176 PlasticClass addToString(String toStringValue); 177 178 /** 179 * Returns true if this class has an implementation of the indicated method, or a super-class provides 180 * a non-abstract implementation. 181 */ 182 boolean isMethodImplemented(MethodDescription description); 183 184 /** 185 * Returns true if this class, or a super-class, implements the indicated interface. 186 * 187 * @param interfaceType 188 * @return true if the interface is implemented 189 */ 190 boolean isInterfaceImplemented(Class interfaceType); 191 192 /** 193 * Returns the name of the super-class of the class being transformed. 194 */ 195 String getSuperClassName(); 196 197 /** 198 * Adds the callback for execution when an instance of the class is instantiated. 199 * 200 * @param callback to execute at instance construction time 201 */ 202 PlasticClass onConstruct(ConstructorCallback callback); 203 }