You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BcelField.java 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.util.List;
  14. import org.aspectj.apache.bcel.classfile.Attribute;
  15. import org.aspectj.apache.bcel.classfile.ConstantPool;
  16. import org.aspectj.apache.bcel.classfile.Field;
  17. import org.aspectj.apache.bcel.classfile.Synthetic;
  18. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  19. import org.aspectj.apache.bcel.generic.FieldGen;
  20. import org.aspectj.util.GenericSignature;
  21. import org.aspectj.util.GenericSignatureParser;
  22. import org.aspectj.weaver.AjAttribute;
  23. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  24. import org.aspectj.weaver.AnnotationAJ;
  25. import org.aspectj.weaver.ISourceContext;
  26. import org.aspectj.weaver.ResolvedMemberImpl;
  27. import org.aspectj.weaver.ResolvedType;
  28. import org.aspectj.weaver.UnresolvedType;
  29. import org.aspectj.weaver.World;
  30. import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
  31. /**
  32. * An AspectJ Field object that is backed by a Bcel Field object.
  33. *
  34. * @author PARC
  35. * @author Andy Clement
  36. */
  37. final class BcelField extends ResolvedMemberImpl {
  38. public static int AccSynthetic = 0x1000;
  39. private Field field;
  40. private boolean isAjSynthetic;
  41. private boolean isSynthetic = false;
  42. private AnnotationAJ[] annotations;
  43. private final World world;
  44. private final BcelObjectType bcelObjectType;
  45. private UnresolvedType genericFieldType = null;
  46. private boolean unpackedGenericSignature = false;
  47. private boolean annotationsOnFieldObjectAreOutOfDate = false;
  48. BcelField(BcelObjectType declaringType, Field field) {
  49. super(FIELD, declaringType.getResolvedTypeX(), field.getModifiers(), field.getName(), field.getSignature());
  50. this.field = field;
  51. this.world = declaringType.getResolvedTypeX().getWorld();
  52. this.bcelObjectType = declaringType;
  53. unpackAttributes(world);
  54. checkedExceptions = UnresolvedType.NONE;
  55. }
  56. /**
  57. * Constructs an instance that wrappers a Field object, but where we do not (yet) have a BcelObjectType - usually because the
  58. * containing type (and this field) are being constructed at runtime (so there is no .class file to retrieve).
  59. */
  60. BcelField(String declaringTypeName, Field field, World world) {
  61. super(FIELD, UnresolvedType.forName(declaringTypeName), field.getModifiers(), field.getName(), field.getSignature());
  62. this.field = field;
  63. this.world = world;
  64. this.bcelObjectType = null;
  65. unpackAttributes(world);
  66. checkedExceptions = UnresolvedType.NONE;
  67. }
  68. private void unpackAttributes(World world) {
  69. Attribute[] attrs = field.getAttributes();
  70. if (attrs != null && attrs.length > 0) {
  71. ISourceContext sourceContext = getSourceContext(world);
  72. List<AjAttribute> as = Utility.readAjAttributes(getDeclaringType().getClassName(), attrs, sourceContext, world,
  73. (bcelObjectType != null ? bcelObjectType.getWeaverVersionAttribute() : WeaverVersionInfo.CURRENT),
  74. new BcelConstantPoolReader(field.getConstantPool()));
  75. as.addAll(AtAjAttributes.readAj5FieldAttributes(field, this, world.resolve(getDeclaringType()), sourceContext,
  76. world.getMessageHandler()));
  77. // FIXME this code has no effect!!!??? it is set to false immediately after the block
  78. // for (AjAttribute a : as) {
  79. // if (a instanceof AjAttribute.AjSynthetic) {
  80. // isAjSynthetic = true;
  81. // } else {
  82. // throw new BCException("weird field attribute " + a);
  83. // }
  84. // }
  85. }
  86. isAjSynthetic = false;
  87. for (int i = attrs.length - 1; i >= 0; i--) {
  88. if (attrs[i] instanceof Synthetic) {
  89. isSynthetic = true;
  90. }
  91. }
  92. // in 1.5, synthetic is a modifier, not an attribute
  93. if ((field.getModifiers() & AccSynthetic) != 0) {
  94. isSynthetic = true;
  95. }
  96. }
  97. @Override
  98. public boolean isAjSynthetic() {
  99. return isAjSynthetic;
  100. }
  101. @Override
  102. public boolean isSynthetic() {
  103. return isSynthetic;
  104. }
  105. @Override
  106. public boolean hasAnnotation(UnresolvedType ofType) {
  107. ensureAnnotationTypesRetrieved();
  108. for (ResolvedType aType : annotationTypes) {
  109. if (aType.equals(ofType)) {
  110. return true;
  111. }
  112. }
  113. return false;
  114. }
  115. @Override
  116. public ResolvedType[] getAnnotationTypes() {
  117. ensureAnnotationTypesRetrieved();
  118. return annotationTypes;
  119. }
  120. @Override
  121. public AnnotationAJ[] getAnnotations() {
  122. ensureAnnotationTypesRetrieved();
  123. return annotations;
  124. }
  125. @Override
  126. public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
  127. ensureAnnotationTypesRetrieved();
  128. for (AnnotationAJ annotation : annotations) {
  129. if (annotation.getTypeName().equals(ofType.getName())) {
  130. return annotation;
  131. }
  132. }
  133. return null;
  134. }
  135. private void ensureAnnotationTypesRetrieved() {
  136. if (annotationTypes == null) {
  137. AnnotationGen annos[] = field.getAnnotations();
  138. if (annos.length == 0) {
  139. annotationTypes = ResolvedType.EMPTY_ARRAY;
  140. annotations = AnnotationAJ.EMPTY_ARRAY;
  141. } else {
  142. int annosCount = annos.length;
  143. annotationTypes = new ResolvedType[annosCount];
  144. annotations = new AnnotationAJ[annosCount];
  145. for (int i = 0; i < annosCount; i++) {
  146. AnnotationGen anno = annos[i];
  147. annotations[i] = new BcelAnnotation(anno, world);
  148. annotationTypes[i] = annotations[i].getType();
  149. }
  150. }
  151. }
  152. }
  153. @Override
  154. public void addAnnotation(AnnotationAJ annotation) {
  155. ensureAnnotationTypesRetrieved();
  156. int len = annotations.length;
  157. AnnotationAJ[] ret = new AnnotationAJ[len + 1];
  158. System.arraycopy(annotations, 0, ret, 0, len);
  159. ret[len] = annotation;
  160. annotations = ret;
  161. ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
  162. System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
  163. newAnnotationTypes[len] = annotation.getType();
  164. annotationTypes = newAnnotationTypes;
  165. annotationsOnFieldObjectAreOutOfDate = true;
  166. }
  167. public void removeAnnotation(AnnotationAJ annotation) {
  168. ensureAnnotationTypesRetrieved();
  169. int len = annotations.length;
  170. AnnotationAJ[] ret = new AnnotationAJ[len - 1];
  171. int p = 0;
  172. for (AnnotationAJ anno : annotations) {
  173. if (!anno.getType().equals(annotation.getType())) {
  174. ret[p++] = anno;
  175. }
  176. }
  177. annotations = ret;
  178. ResolvedType[] newAnnotationTypes = new ResolvedType[len - 1];
  179. p = 0;
  180. for (ResolvedType anno : annotationTypes) {
  181. if (!anno.equals(annotation.getType())) {
  182. newAnnotationTypes[p++] = anno;
  183. }
  184. }
  185. annotationTypes = newAnnotationTypes;
  186. annotationsOnFieldObjectAreOutOfDate = true;
  187. }
  188. /**
  189. * Unpack the generic signature attribute if there is one and we haven't already done so, then find the true field type of this
  190. * field (eg. List<String>).
  191. */
  192. @Override
  193. public UnresolvedType getGenericReturnType() {
  194. unpackGenericSignature();
  195. return genericFieldType;
  196. }
  197. public Field getFieldAsIs() {
  198. return field;
  199. }
  200. public Field getField(ConstantPool cpool) {
  201. if (!annotationsOnFieldObjectAreOutOfDate) {
  202. return field;
  203. }
  204. FieldGen newFieldGen = new FieldGen(field, cpool);
  205. newFieldGen.removeAnnotations();
  206. // List<AnnotationGen> alreadyHas = fg.getAnnotations();
  207. // if (annotations != null) {
  208. // fg.removeAnnotations();
  209. for (AnnotationAJ annotation : annotations) {
  210. newFieldGen.addAnnotation(new AnnotationGen(((BcelAnnotation) annotation).getBcelAnnotation(), cpool, true));
  211. }
  212. // for (int i = 0; i < annotations.length; i++) {
  213. // AnnotationAJ array_element = annotations[i];
  214. // boolean alreadyHasIt = false;
  215. // for (AnnotationGen gen : alreadyHas) {
  216. // if (gen.getTypeName().equals(array_element.getTypeName())) {
  217. // alreadyHasIt = true;
  218. // break;
  219. // }
  220. // }
  221. // if (!alreadyHasIt) {
  222. // fg.addAnnotation(new AnnotationGen(((BcelAnnotation) array_element).getBcelAnnotation(), cpg, true));
  223. // // }
  224. // // }
  225. // }
  226. field = newFieldGen.getField();
  227. annotationsOnFieldObjectAreOutOfDate = false; // we are now correct again
  228. return field;
  229. }
  230. private void unpackGenericSignature() {
  231. if (unpackedGenericSignature) {
  232. return;
  233. }
  234. if (!world.isInJava5Mode()) {
  235. this.genericFieldType = getReturnType();
  236. return;
  237. }
  238. unpackedGenericSignature = true;
  239. String gSig = field.getGenericSignature();
  240. if (gSig != null) {
  241. // get from generic
  242. GenericSignature.FieldTypeSignature fts = new GenericSignatureParser().parseAsFieldSignature(gSig);
  243. GenericSignature.ClassSignature genericTypeSig = bcelObjectType.getGenericClassTypeSignature();
  244. GenericSignature.FormalTypeParameter[] parentFormals = bcelObjectType.getAllFormals();
  245. GenericSignature.FormalTypeParameter[] typeVars = ((genericTypeSig == null) ? GenericSignature.FormalTypeParameter.NONE
  246. : genericTypeSig.formalTypeParameters);
  247. GenericSignature.FormalTypeParameter[] formals = new GenericSignature.FormalTypeParameter[parentFormals.length
  248. + typeVars.length];
  249. // put method formal in front of type formals for overriding in
  250. // lookup
  251. System.arraycopy(typeVars, 0, formals, 0, typeVars.length);
  252. System.arraycopy(parentFormals, 0, formals, typeVars.length, parentFormals.length);
  253. try {
  254. genericFieldType = BcelGenericSignatureToTypeXConverter.fieldTypeSignature2TypeX(fts, formals, world);
  255. } catch (GenericSignatureFormatException e) {
  256. // development bug, fail fast with good info
  257. throw new IllegalStateException("While determing the generic field type of " + this.toString()
  258. + " with generic signature " + gSig + " the following error was detected: " + e.getMessage());
  259. }
  260. } else {
  261. genericFieldType = getReturnType();
  262. }
  263. }
  264. @Override
  265. public void evictWeavingState() {
  266. if (field != null) {
  267. unpackGenericSignature();
  268. unpackAttributes(world);
  269. ensureAnnotationTypesRetrieved();
  270. // this.sourceContext = SourceContextImpl.UNKNOWN_SOURCE_CONTEXT;
  271. field = null;
  272. }
  273. }
  274. }