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.

BcelObjectType.java 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Contributors
  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. * RonBodkin/AndyClement optimizations for memory consumption/speed
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.io.PrintStream;
  15. import java.lang.ref.WeakReference;
  16. import java.lang.reflect.Modifier;
  17. import java.util.ArrayList;
  18. import java.util.Arrays;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.List;
  22. import java.util.Set;
  23. import org.aspectj.apache.bcel.classfile.Attribute;
  24. import org.aspectj.apache.bcel.classfile.AttributeUtils;
  25. import org.aspectj.apache.bcel.classfile.ConstantClass;
  26. import org.aspectj.apache.bcel.classfile.ConstantPool;
  27. import org.aspectj.apache.bcel.classfile.EnclosingMethod;
  28. import org.aspectj.apache.bcel.classfile.Field;
  29. import org.aspectj.apache.bcel.classfile.InnerClass;
  30. import org.aspectj.apache.bcel.classfile.InnerClasses;
  31. import org.aspectj.apache.bcel.classfile.JavaClass;
  32. import org.aspectj.apache.bcel.classfile.Method;
  33. import org.aspectj.apache.bcel.classfile.Signature;
  34. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  35. import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
  36. import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
  37. import org.aspectj.asm.AsmManager;
  38. import org.aspectj.bridge.IMessageHandler;
  39. import org.aspectj.bridge.MessageUtil;
  40. import org.aspectj.util.GenericSignature;
  41. import org.aspectj.util.GenericSignature.FormalTypeParameter;
  42. import org.aspectj.weaver.AbstractReferenceTypeDelegate;
  43. import org.aspectj.weaver.AjAttribute;
  44. import org.aspectj.weaver.AjcMemberMaker;
  45. import org.aspectj.weaver.AnnotationAJ;
  46. import org.aspectj.weaver.AnnotationTargetKind;
  47. import org.aspectj.weaver.BCException;
  48. import org.aspectj.weaver.BindingScope;
  49. import org.aspectj.weaver.ConcreteTypeMunger;
  50. import org.aspectj.weaver.ISourceContext;
  51. import org.aspectj.weaver.ReferenceType;
  52. import org.aspectj.weaver.ResolvedMember;
  53. import org.aspectj.weaver.ResolvedPointcutDefinition;
  54. import org.aspectj.weaver.ResolvedType;
  55. import org.aspectj.weaver.SourceContextImpl;
  56. import org.aspectj.weaver.TypeVariable;
  57. import org.aspectj.weaver.UnresolvedType;
  58. import org.aspectj.weaver.WeaverStateInfo;
  59. import org.aspectj.weaver.World;
  60. import org.aspectj.weaver.bcel.BcelGenericSignatureToTypeXConverter.GenericSignatureFormatException;
  61. import org.aspectj.weaver.patterns.Declare;
  62. import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
  63. import org.aspectj.weaver.patterns.DeclarePrecedence;
  64. import org.aspectj.weaver.patterns.FormalBinding;
  65. import org.aspectj.weaver.patterns.IScope;
  66. import org.aspectj.weaver.patterns.PerClause;
  67. public class BcelObjectType extends AbstractReferenceTypeDelegate {
  68. public JavaClass javaClass;
  69. private boolean artificial; // Was the BcelObject built from an artificial set of bytes? Or from the real ondisk stuff?
  70. private LazyClassGen lazyClassGen = null; // set lazily if it's an aspect
  71. private int modifiers;
  72. private String className;
  73. private String superclassSignature;
  74. private String superclassName;
  75. private String[] interfaceSignatures;
  76. private ResolvedMember[] fields = null;
  77. private ResolvedMember[] methods = null;
  78. private ResolvedType[] annotationTypes = null;
  79. private AnnotationAJ[] annotations = null;
  80. private TypeVariable[] typeVars = null;
  81. private String retentionPolicy;
  82. private AnnotationTargetKind[] annotationTargetKinds;
  83. // Aspect related stuff (pointcuts *could* be in a java class)
  84. private AjAttribute.WeaverVersionInfo wvInfo = AjAttribute.WeaverVersionInfo.UNKNOWN;
  85. private ResolvedPointcutDefinition[] pointcuts = null;
  86. private ResolvedMember[] privilegedAccess = null;
  87. private WeaverStateInfo weaverState = null;
  88. private PerClause perClause = null;
  89. private List<ConcreteTypeMunger> typeMungers = Collections.emptyList();
  90. private List<Declare> declares = Collections.emptyList();
  91. private GenericSignature.FormalTypeParameter[] formalsForResolution = null;
  92. private String declaredSignature = null;
  93. private boolean hasBeenWoven = false;
  94. private boolean isGenericType = false;
  95. private boolean isInterface;
  96. private boolean isEnum;
  97. private boolean isAnnotation;
  98. private boolean isAnonymous;
  99. private boolean isNested;
  100. private boolean isObject = false; // set upon construction
  101. private boolean isAnnotationStyleAspect = false;// set upon construction
  102. private boolean isCodeStyleAspect = false; // not redundant with field
  103. // above!
  104. private WeakReference<ResolvedType> superTypeReference = new WeakReference<>(null);
  105. private WeakReference<ResolvedType[]> superInterfaceReferences = new WeakReference<>(null);
  106. private int bitflag = 0x0000;
  107. // discovery bits
  108. private static final int DISCOVERED_ANNOTATION_RETENTION_POLICY = 0x0001;
  109. private static final int UNPACKED_GENERIC_SIGNATURE = 0x0002;
  110. private static final int UNPACKED_AJATTRIBUTES = 0x0004; // see note(1)
  111. // below
  112. private static final int DISCOVERED_ANNOTATION_TARGET_KINDS = 0x0008;
  113. private static final int DISCOVERED_DECLARED_SIGNATURE = 0x0010;
  114. private static final int DISCOVERED_WHETHER_ANNOTATION_STYLE = 0x0020;
  115. private static final int ANNOTATION_UNPACK_IN_PROGRESS = 0x0100;
  116. private static final String[] NO_INTERFACE_SIGS = new String[] {};
  117. /*
  118. * Notes: note(1): in some cases (perclause inheritance) we encounter unpacked state when calling getPerClause
  119. *
  120. * note(2): A BcelObjectType is 'damaged' if it has been modified from what was original constructed from the bytecode. This
  121. * currently happens if the parents are modified or an annotation is added - ideally BcelObjectType should be immutable but
  122. * that's a bigger piece of work. XXX
  123. */
  124. BcelObjectType(ReferenceType resolvedTypeX, JavaClass javaClass, boolean artificial, boolean exposedToWeaver) {
  125. super(resolvedTypeX, exposedToWeaver);
  126. this.javaClass = javaClass;
  127. this.artificial = artificial;
  128. initializeFromJavaclass();
  129. // ATAJ: set the delegate right now for @AJ pointcut, else it is done
  130. // too late to lookup
  131. // @AJ pc refs annotation in class hierarchy
  132. resolvedTypeX.setDelegate(this);
  133. ISourceContext sourceContext = resolvedTypeX.getSourceContext();
  134. if (sourceContext == SourceContextImpl.UNKNOWN_SOURCE_CONTEXT) {
  135. sourceContext = new SourceContextImpl(this);
  136. setSourceContext(sourceContext);
  137. }
  138. // this should only ever be java.lang.Object which is
  139. // the only class in Java-1.4 with no superclasses
  140. isObject = (javaClass.getSuperclassNameIndex() == 0);
  141. ensureAspectJAttributesUnpacked();
  142. // Experimental code leading to undesired ripple effects elsewhere, requiring more rework
  143. /*
  144. final String fileName = javaClass.getFileName();
  145. final String sourceFileName = javaClass.getSourceFileName();
  146. if (fileName == null || !fileName.endsWith(".class"))
  147. setSourcefilename(sourceFileName);
  148. else if (sourceFileName == null || sourceFileName.isEmpty() || sourceFileName.endsWith(".class"))
  149. setSourcefilename(fileName);
  150. else
  151. setSourcefilename(fileName + " (from " + sourceFileName + ")");
  152. */
  153. setSourcefilename(javaClass.getSourceFileName());
  154. }
  155. // repeat initialization
  156. public void setJavaClass(JavaClass newclass, boolean artificial) {
  157. this.javaClass = newclass;
  158. this.artificial = artificial;
  159. resetState();
  160. initializeFromJavaclass();
  161. }
  162. @Override
  163. public boolean isCacheable() {
  164. return true;
  165. }
  166. private void initializeFromJavaclass() {
  167. isInterface = javaClass.isInterface();
  168. isEnum = javaClass.isEnum();
  169. isAnnotation = javaClass.isAnnotation();
  170. isAnonymous = javaClass.isAnonymous();
  171. isNested = javaClass.isNested();
  172. modifiers = javaClass.getModifiers();
  173. superclassName = javaClass.getSuperclassName();
  174. className = javaClass.getClassName();
  175. cachedGenericClassTypeSignature = null;
  176. }
  177. // --- getters
  178. // Java related
  179. public boolean isInterface() {
  180. return isInterface;
  181. }
  182. public boolean isEnum() {
  183. return isEnum;
  184. }
  185. public boolean isAnnotation() {
  186. return isAnnotation;
  187. }
  188. public boolean isAnonymous() {
  189. return isAnonymous;
  190. }
  191. public boolean isNested() {
  192. return isNested;
  193. }
  194. public int getModifiers() {
  195. return modifiers;
  196. }
  197. /**
  198. * Must take into account generic signature
  199. */
  200. public ResolvedType getSuperclass() {
  201. if (isObject) {
  202. return null;
  203. }
  204. ResolvedType supertype = superTypeReference.get();
  205. if (supertype == null) {
  206. ensureGenericSignatureUnpacked();
  207. if (superclassSignature == null) {
  208. if (superclassName == null) {
  209. superclassName = javaClass.getSuperclassName();
  210. }
  211. superclassSignature = getResolvedTypeX().getWorld().resolve(UnresolvedType.forName(superclassName)).getSignature();
  212. }
  213. World world = getResolvedTypeX().getWorld();
  214. supertype = world.resolve(UnresolvedType.forSignature(superclassSignature));
  215. superTypeReference = new WeakReference<>(supertype);
  216. }
  217. return supertype;
  218. }
  219. public World getWorld() {
  220. return getResolvedTypeX().getWorld();
  221. }
  222. /**
  223. * Retrieves the declared interfaces - this allows for the generic signature on a type. If specified then the generic signature
  224. * is used to work out the types - this gets around the results of erasure when the class was originally compiled.
  225. */
  226. public ResolvedType[] getDeclaredInterfaces() {
  227. ResolvedType[] cachedInterfaceTypes = superInterfaceReferences.get();
  228. if (cachedInterfaceTypes == null) {
  229. ensureGenericSignatureUnpacked();
  230. ResolvedType[] interfaceTypes = null;
  231. if (interfaceSignatures == null) {
  232. String[] names = javaClass.getInterfaceNames();
  233. if (names.length == 0) {
  234. interfaceSignatures = NO_INTERFACE_SIGS;
  235. interfaceTypes = ResolvedType.NONE;
  236. } else {
  237. interfaceSignatures = new String[names.length];
  238. interfaceTypes = new ResolvedType[names.length];
  239. for (int i = 0, len = names.length; i < len; i++) {
  240. interfaceTypes[i] = getResolvedTypeX().getWorld().resolve(UnresolvedType.forName(names[i]));
  241. interfaceSignatures[i] = interfaceTypes[i].getSignature();
  242. }
  243. }
  244. } else {
  245. interfaceTypes = new ResolvedType[interfaceSignatures.length];
  246. for (int i = 0, len = interfaceSignatures.length; i < len; i++) {
  247. interfaceTypes[i] = getResolvedTypeX().getWorld().resolve(UnresolvedType.forSignature(interfaceSignatures[i]));
  248. }
  249. }
  250. superInterfaceReferences = new WeakReference<>(interfaceTypes);
  251. return interfaceTypes;
  252. } else {
  253. return cachedInterfaceTypes;
  254. }
  255. }
  256. public ResolvedMember[] getDeclaredMethods() {
  257. ensureGenericSignatureUnpacked();
  258. if (methods == null) {
  259. Method[] ms = javaClass.getMethods();
  260. ResolvedMember[] newMethods = new ResolvedMember[ms.length];
  261. for (int i = ms.length - 1; i >= 0; i--) {
  262. newMethods[i] = new BcelMethod(this, ms[i]);
  263. }
  264. methods = newMethods;
  265. }
  266. return methods;
  267. }
  268. public ResolvedMember[] getDeclaredFields() {
  269. ensureGenericSignatureUnpacked();
  270. if (fields == null) {
  271. Field[] fs = javaClass.getFields();
  272. ResolvedMember[] newfields = new ResolvedMember[fs.length];
  273. for (int i = 0, len = fs.length; i < len; i++) {
  274. newfields[i] = new BcelField(this, fs[i]);
  275. }
  276. fields = newfields;
  277. }
  278. return fields;
  279. }
  280. public TypeVariable[] getTypeVariables() {
  281. if (!isGeneric()) {
  282. return TypeVariable.NONE;
  283. }
  284. if (typeVars == null) {
  285. GenericSignature.ClassSignature classSig = getGenericClassTypeSignature();
  286. typeVars = new TypeVariable[classSig.formalTypeParameters.length];
  287. for (int i = 0; i < typeVars.length; i++) {
  288. GenericSignature.FormalTypeParameter ftp = classSig.formalTypeParameters[i];
  289. try {
  290. typeVars[i] = BcelGenericSignatureToTypeXConverter.formalTypeParameter2TypeVariable(ftp,
  291. classSig.formalTypeParameters, getResolvedTypeX().getWorld());
  292. } catch (GenericSignatureFormatException e) {
  293. // this is a development bug, so fail fast with good info
  294. throw new IllegalStateException("While getting the type variables for type " + this.toString()
  295. + " with generic signature " + classSig + " the following error condition was detected: "
  296. + e.getMessage());
  297. }
  298. }
  299. }
  300. return typeVars;
  301. }
  302. public Collection<ConcreteTypeMunger> getTypeMungers() {
  303. return typeMungers;
  304. }
  305. public Collection<Declare> getDeclares() {
  306. return declares;
  307. }
  308. public Collection<ResolvedMember> getPrivilegedAccesses() {
  309. if (privilegedAccess == null) {
  310. return Collections.emptyList();
  311. }
  312. return Arrays.asList(privilegedAccess);
  313. }
  314. public ResolvedMember[] getDeclaredPointcuts() {
  315. return pointcuts;
  316. }
  317. public boolean isAspect() {
  318. return perClause != null;
  319. }
  320. /**
  321. * Check if the type is an @AJ aspect (no matter if used from an LTW point of view). Such aspects are annotated with @Aspect
  322. *
  323. * @return true for @AJ aspect
  324. */
  325. public boolean isAnnotationStyleAspect() {
  326. if ((bitflag & DISCOVERED_WHETHER_ANNOTATION_STYLE) == 0) {
  327. bitflag |= DISCOVERED_WHETHER_ANNOTATION_STYLE;
  328. isAnnotationStyleAspect = !isCodeStyleAspect && hasAnnotation(AjcMemberMaker.ASPECT_ANNOTATION);
  329. }
  330. return isAnnotationStyleAspect;
  331. }
  332. /**
  333. * Process any org.aspectj.weaver attributes stored against the class.
  334. */
  335. private void ensureAspectJAttributesUnpacked() {
  336. if ((bitflag & UNPACKED_AJATTRIBUTES) != 0) {
  337. return;
  338. }
  339. bitflag |= UNPACKED_AJATTRIBUTES;
  340. IMessageHandler msgHandler = getResolvedTypeX().getWorld().getMessageHandler();
  341. // Pass in empty list that can store things for readAj5 to process
  342. List<AjAttribute> l = null;
  343. try {
  344. l = Utility.readAjAttributes(className, javaClass.getAttributes(), getResolvedTypeX().getSourceContext(),
  345. getResolvedTypeX().getWorld(), AjAttribute.WeaverVersionInfo.UNKNOWN,
  346. new BcelConstantPoolReader(javaClass.getConstantPool()));
  347. } catch (RuntimeException re) {
  348. throw new RuntimeException("Problem processing attributes in " + javaClass.getFileName(), re);
  349. }
  350. List<ResolvedPointcutDefinition> pointcuts = new ArrayList<>();
  351. typeMungers = new ArrayList<>();
  352. declares = new ArrayList<>();
  353. processAttributes(l, pointcuts, false);
  354. ReferenceType type = getResolvedTypeX();
  355. AsmManager asmManager = ((BcelWorld) type.getWorld()).getModelAsAsmManager();
  356. l = AtAjAttributes.readAj5ClassAttributes(asmManager, javaClass, type, type.getSourceContext(), msgHandler,
  357. isCodeStyleAspect);
  358. AjAttribute.Aspect deferredAspectAttribute = processAttributes(l, pointcuts, true);
  359. if (pointcuts.size() == 0) {
  360. this.pointcuts = ResolvedPointcutDefinition.NO_POINTCUTS;
  361. } else {
  362. this.pointcuts = pointcuts.toArray(ResolvedPointcutDefinition.NO_POINTCUTS);
  363. }
  364. resolveAnnotationDeclares(l);
  365. if (deferredAspectAttribute != null) {
  366. // we can finally process the aspect and its associated perclause...
  367. perClause = deferredAspectAttribute.reifyFromAtAspectJ(this.getResolvedTypeX());
  368. }
  369. if (isAspect() && !Modifier.isAbstract(getModifiers()) && isGeneric()) {
  370. msgHandler.handleMessage(MessageUtil.error("The generic aspect '" + getResolvedTypeX().getName()
  371. + "' must be declared abstract", getResolvedTypeX().getSourceLocation()));
  372. }
  373. }
  374. private AjAttribute.Aspect processAttributes(List<AjAttribute> attributeList, List<ResolvedPointcutDefinition> pointcuts,
  375. boolean fromAnnotations) {
  376. AjAttribute.Aspect deferredAspectAttribute = null;
  377. for (AjAttribute a : attributeList) {
  378. if (a instanceof AjAttribute.Aspect) {
  379. if (fromAnnotations) {
  380. deferredAspectAttribute = (AjAttribute.Aspect) a;
  381. } else {
  382. perClause = ((AjAttribute.Aspect) a).reify(this.getResolvedTypeX());
  383. isCodeStyleAspect = true;
  384. }
  385. } else if (a instanceof AjAttribute.PointcutDeclarationAttribute) {
  386. pointcuts.add(((AjAttribute.PointcutDeclarationAttribute) a).reify());
  387. } else if (a instanceof AjAttribute.WeaverState) {
  388. weaverState = ((AjAttribute.WeaverState) a).reify();
  389. } else if (a instanceof AjAttribute.TypeMunger) {
  390. typeMungers.add(((AjAttribute.TypeMunger) a).reify(getResolvedTypeX().getWorld(), getResolvedTypeX()));
  391. } else if (a instanceof AjAttribute.DeclareAttribute) {
  392. declares.add(((AjAttribute.DeclareAttribute) a).getDeclare());
  393. } else if (a instanceof AjAttribute.PrivilegedAttribute) {
  394. AjAttribute.PrivilegedAttribute privAttribute = (AjAttribute.PrivilegedAttribute) a;
  395. privilegedAccess = privAttribute.getAccessedMembers();
  396. } else if (a instanceof AjAttribute.SourceContextAttribute) {
  397. if (getResolvedTypeX().getSourceContext() instanceof SourceContextImpl) {
  398. AjAttribute.SourceContextAttribute sca = (AjAttribute.SourceContextAttribute) a;
  399. ((SourceContextImpl) getResolvedTypeX().getSourceContext()).configureFromAttribute(sca.getSourceFileName(),
  400. sca.getLineBreaks());
  401. setSourcefilename(sca.getSourceFileName());
  402. }
  403. } else if (a instanceof AjAttribute.WeaverVersionInfo) {
  404. // Set the weaver version used to build this type
  405. wvInfo = (AjAttribute.WeaverVersionInfo) a;
  406. } else {
  407. throw new BCException("bad attribute " + a);
  408. }
  409. }
  410. return deferredAspectAttribute;
  411. }
  412. /**
  413. * Extra processing step needed because declares that come from annotations are not pre-resolved. We can't do the resolution
  414. * until *after* the pointcuts have been resolved.
  415. */
  416. private void resolveAnnotationDeclares(List<AjAttribute> attributeList) {
  417. FormalBinding[] bindings = FormalBinding.NONE;
  418. IScope bindingScope = new BindingScope(getResolvedTypeX(), getResolvedTypeX().getSourceContext(), bindings);
  419. for (AjAttribute a : attributeList) {
  420. if (a instanceof AjAttribute.DeclareAttribute) {
  421. Declare decl = (((AjAttribute.DeclareAttribute) a).getDeclare());
  422. if (decl instanceof DeclareErrorOrWarning) {
  423. decl.resolve(bindingScope);
  424. } else if (decl instanceof DeclarePrecedence) {
  425. ((DeclarePrecedence) decl).setScopeForResolution(bindingScope);
  426. }
  427. }
  428. }
  429. }
  430. public PerClause getPerClause() {
  431. ensureAspectJAttributesUnpacked();
  432. return perClause;
  433. }
  434. public JavaClass getJavaClass() {
  435. return javaClass;
  436. }
  437. /**
  438. * @return true if built from bytes obtained from somewhere. False if built from bytes retrieved from disk.
  439. */
  440. public boolean isArtificial() {
  441. return artificial;
  442. }
  443. public void resetState() {
  444. if (javaClass == null) {
  445. // we might store the classname and allow reloading?
  446. // At this point we are relying on the world to not evict if it
  447. // might want to reweave multiple times
  448. throw new BCException("can't weave evicted type");
  449. }
  450. bitflag = 0x0000;
  451. this.annotationTypes = null;
  452. this.annotations = null;
  453. this.interfaceSignatures = null;
  454. this.superclassSignature = null;
  455. this.superclassName = null;
  456. this.fields = null;
  457. this.methods = null;
  458. this.pointcuts = null;
  459. this.perClause = null;
  460. this.weaverState = null;
  461. this.lazyClassGen = null;
  462. hasBeenWoven = false;
  463. isObject = (javaClass.getSuperclassNameIndex() == 0);
  464. isAnnotationStyleAspect = false;
  465. ensureAspectJAttributesUnpacked();
  466. }
  467. public void finishedWith() {
  468. // memory usage experiments....
  469. // this.interfaces = null;
  470. // this.superClass = null;
  471. // this.fields = null;
  472. // this.methods = null;
  473. // this.pointcuts = null;
  474. // this.perClause = null;
  475. // this.weaverState = null;
  476. // this.lazyClassGen = null;
  477. // this next line frees up memory, but need to understand incremental
  478. // implications
  479. // before leaving it in.
  480. // getResolvedTypeX().setSourceContext(null);
  481. }
  482. public WeaverStateInfo getWeaverState() {
  483. return weaverState;
  484. }
  485. void setWeaverState(WeaverStateInfo weaverState) {
  486. this.weaverState = weaverState;
  487. }
  488. public void printWackyStuff(PrintStream out) {
  489. if (typeMungers.size() > 0) {
  490. out.println(" TypeMungers: " + typeMungers);
  491. }
  492. if (declares.size() > 0) {
  493. out.println(" declares: " + declares);
  494. }
  495. }
  496. /**
  497. * Return the lazyClassGen associated with this type. For aspect types, this value will be cached, since it is used to inline
  498. * advice. For non-aspect types, this lazyClassGen is always newly constructed.
  499. */
  500. public LazyClassGen getLazyClassGen() {
  501. LazyClassGen ret = lazyClassGen;
  502. if (ret == null) {
  503. // System.err.println("creating lazy class gen for: " + this);
  504. ret = new LazyClassGen(this);
  505. // ret.print(System.err);
  506. // System.err.println("made LCG from : " +
  507. // this.getJavaClass().getSuperclassName );
  508. if (isAspect()) {
  509. lazyClassGen = ret;
  510. }
  511. }
  512. return ret;
  513. }
  514. public boolean isSynthetic() {
  515. return getResolvedTypeX().isSynthetic();
  516. }
  517. public AjAttribute.WeaverVersionInfo getWeaverVersionAttribute() {
  518. return wvInfo;
  519. }
  520. // -- annotation related
  521. public ResolvedType[] getAnnotationTypes() {
  522. ensureAnnotationsUnpacked();
  523. return annotationTypes;
  524. }
  525. public AnnotationAJ[] getAnnotations() {
  526. ensureAnnotationsUnpacked();
  527. return annotations;
  528. }
  529. public boolean hasAnnotations() {
  530. ensureAnnotationsUnpacked();
  531. return annotations.length != 0;
  532. }
  533. public boolean hasAnnotation(UnresolvedType ofType) {
  534. // Due to re-entrancy we may be in the middle of unpacking the annotations already... in which case use this slow
  535. // alternative until the stack unwinds itself
  536. if (isUnpackingAnnotations()) {
  537. AnnotationGen annos[] = javaClass.getAnnotations();
  538. if (annos == null || annos.length == 0) {
  539. return false;
  540. } else {
  541. String lookingForSignature = ofType.getSignature();
  542. for (AnnotationGen annotation : annos) {
  543. if (lookingForSignature.equals(annotation.getTypeSignature())) {
  544. return true;
  545. }
  546. }
  547. }
  548. return false;
  549. }
  550. ensureAnnotationsUnpacked();
  551. for (int i = 0, max = annotationTypes.length; i < max; i++) {
  552. UnresolvedType ax = annotationTypes[i];
  553. if (ax == null) {
  554. throw new RuntimeException("Annotation entry " + i + " on type " + this.getResolvedTypeX().getName() + " is null!");
  555. }
  556. if (ax.equals(ofType)) {
  557. return true;
  558. }
  559. }
  560. return false;
  561. }
  562. public boolean isAnnotationWithRuntimeRetention() {
  563. return (getRetentionPolicy() == null ? false : getRetentionPolicy().equals("RUNTIME"));
  564. }
  565. public String getRetentionPolicy() {
  566. if ((bitflag & DISCOVERED_ANNOTATION_RETENTION_POLICY) == 0) {
  567. bitflag |= DISCOVERED_ANNOTATION_RETENTION_POLICY;
  568. retentionPolicy = null; // null means we have no idea
  569. if (isAnnotation()) {
  570. ensureAnnotationsUnpacked();
  571. for (int i = annotations.length - 1; i >= 0; i--) {
  572. AnnotationAJ ax = annotations[i];
  573. if (ax.getTypeName().equals(UnresolvedType.AT_RETENTION.getName())) {
  574. List<NameValuePair> values = ((BcelAnnotation) ax).getBcelAnnotation().getValues();
  575. for (NameValuePair element : values) {
  576. EnumElementValue v = (EnumElementValue) element.getValue();
  577. retentionPolicy = v.getEnumValueString();
  578. return retentionPolicy;
  579. }
  580. }
  581. }
  582. }
  583. }
  584. return retentionPolicy;
  585. }
  586. public boolean canAnnotationTargetType() {
  587. AnnotationTargetKind[] targetKinds = getAnnotationTargetKinds();
  588. if (targetKinds == null) {
  589. return true;
  590. }
  591. for (AnnotationTargetKind targetKind : targetKinds) {
  592. if (targetKind.equals(AnnotationTargetKind.TYPE)) {
  593. return true;
  594. }
  595. }
  596. return false;
  597. }
  598. public AnnotationTargetKind[] getAnnotationTargetKinds() {
  599. if ((bitflag & DISCOVERED_ANNOTATION_TARGET_KINDS) != 0) {
  600. return annotationTargetKinds;
  601. }
  602. bitflag |= DISCOVERED_ANNOTATION_TARGET_KINDS;
  603. annotationTargetKinds = null; // null means we have no idea or the
  604. // @Target annotation hasn't been used
  605. List<AnnotationTargetKind> targetKinds = new ArrayList<>();
  606. if (isAnnotation()) {
  607. AnnotationAJ[] annotationsOnThisType = getAnnotations();
  608. for (AnnotationAJ a : annotationsOnThisType) {
  609. if (a.getTypeName().equals(UnresolvedType.AT_TARGET.getName())) {
  610. Set<String> targets = a.getTargets();
  611. if (targets != null) {
  612. for (String targetKind : targets) {
  613. if (targetKind.equals("ANNOTATION_TYPE")) {
  614. targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
  615. } else if (targetKind.equals("CONSTRUCTOR")) {
  616. targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
  617. } else if (targetKind.equals("FIELD")) {
  618. targetKinds.add(AnnotationTargetKind.FIELD);
  619. } else if (targetKind.equals("LOCAL_VARIABLE")) {
  620. targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
  621. } else if (targetKind.equals("METHOD")) {
  622. targetKinds.add(AnnotationTargetKind.METHOD);
  623. } else if (targetKind.equals("PACKAGE")) {
  624. targetKinds.add(AnnotationTargetKind.PACKAGE);
  625. } else if (targetKind.equals("PARAMETER")) {
  626. targetKinds.add(AnnotationTargetKind.PARAMETER);
  627. } else if (targetKind.equals("TYPE")) {
  628. targetKinds.add(AnnotationTargetKind.TYPE);
  629. }
  630. }
  631. }
  632. }
  633. }
  634. if (!targetKinds.isEmpty()) {
  635. annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
  636. return targetKinds.toArray(annotationTargetKinds);
  637. }
  638. }
  639. return annotationTargetKinds;
  640. }
  641. // --- unpacking methods
  642. private boolean isUnpackingAnnotations() {
  643. return (bitflag & ANNOTATION_UNPACK_IN_PROGRESS) != 0;
  644. }
  645. private void ensureAnnotationsUnpacked() {
  646. if (isUnpackingAnnotations()) {
  647. throw new BCException("Re-entered weaver instance whilst unpacking annotations on " + this.className);
  648. }
  649. if (annotationTypes == null) {
  650. try {
  651. bitflag |= ANNOTATION_UNPACK_IN_PROGRESS;
  652. AnnotationGen annos[] = javaClass.getAnnotations();
  653. if (annos == null || annos.length == 0) {
  654. annotationTypes = ResolvedType.NONE;
  655. annotations = AnnotationAJ.EMPTY_ARRAY;
  656. } else {
  657. World w = getResolvedTypeX().getWorld();
  658. annotationTypes = new ResolvedType[annos.length];
  659. annotations = new AnnotationAJ[annos.length];
  660. for (int i = 0; i < annos.length; i++) {
  661. AnnotationGen annotation = annos[i];
  662. String typeSignature = annotation.getTypeSignature();
  663. ResolvedType rType = w.resolve(UnresolvedType.forSignature(typeSignature));
  664. if (rType == null) {
  665. throw new RuntimeException("Whilst unpacking annotations on '" + getResolvedTypeX().getName()
  666. + "', failed to resolve type '" + typeSignature + "'");
  667. }
  668. annotationTypes[i] = rType;
  669. annotations[i] = new BcelAnnotation(annotation, rType);
  670. }
  671. }
  672. } finally {
  673. bitflag &= ~ANNOTATION_UNPACK_IN_PROGRESS;
  674. }
  675. }
  676. }
  677. // ---
  678. public String getDeclaredGenericSignature() {
  679. ensureGenericInfoProcessed();
  680. return declaredSignature;
  681. }
  682. private void ensureGenericSignatureUnpacked() {
  683. if ((bitflag & UNPACKED_GENERIC_SIGNATURE) != 0) {
  684. return;
  685. }
  686. bitflag |= UNPACKED_GENERIC_SIGNATURE;
  687. if (!getResolvedTypeX().getWorld().isInJava5Mode()) {
  688. return;
  689. }
  690. GenericSignature.ClassSignature cSig = getGenericClassTypeSignature();
  691. if (cSig != null) {
  692. formalsForResolution = cSig.formalTypeParameters;
  693. if (isNested()) {
  694. // we have to find any type variables from the outer type before
  695. // proceeding with resolution.
  696. GenericSignature.FormalTypeParameter[] extraFormals = getFormalTypeParametersFromOuterClass();
  697. if (extraFormals.length > 0) {
  698. List<FormalTypeParameter> allFormals = new ArrayList<>();
  699. Collections.addAll(allFormals, formalsForResolution);
  700. Collections.addAll(allFormals, extraFormals);
  701. formalsForResolution = new GenericSignature.FormalTypeParameter[allFormals.size()];
  702. allFormals.toArray(formalsForResolution);
  703. }
  704. }
  705. GenericSignature.ClassTypeSignature superSig = cSig.superclassSignature;
  706. try {
  707. // this.superClass =
  708. // BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(
  709. // superSig, formalsForResolution,
  710. // getResolvedTypeX().getWorld());
  711. ResolvedType rt = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(superSig, formalsForResolution,
  712. getResolvedTypeX().getWorld());
  713. this.superclassSignature = rt.getSignature();
  714. this.superclassName = rt.getName();
  715. } catch (GenericSignatureFormatException e) {
  716. // development bug, fail fast with good info
  717. throw new IllegalStateException("While determining the generic superclass of " + this.className
  718. + " with generic signature " + getDeclaredGenericSignature() + " the following error was detected: "
  719. + e.getMessage());
  720. }
  721. // this.interfaces = new
  722. // ResolvedType[cSig.superInterfaceSignatures.length];
  723. if (cSig.superInterfaceSignatures.length == 0) {
  724. this.interfaceSignatures = NO_INTERFACE_SIGS;
  725. } else {
  726. this.interfaceSignatures = new String[cSig.superInterfaceSignatures.length];
  727. for (int i = 0; i < cSig.superInterfaceSignatures.length; i++) {
  728. try {
  729. // this.interfaces[i] =
  730. // BcelGenericSignatureToTypeXConverter.
  731. // classTypeSignature2TypeX(
  732. // cSig.superInterfaceSignatures[i],
  733. // formalsForResolution,
  734. // getResolvedTypeX().getWorld());
  735. this.interfaceSignatures[i] = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX(
  736. cSig.superInterfaceSignatures[i], formalsForResolution, getResolvedTypeX().getWorld())
  737. .getSignature();
  738. } catch (GenericSignatureFormatException e) {
  739. // development bug, fail fast with good info
  740. throw new IllegalStateException("While determing the generic superinterfaces of " + this.className
  741. + " with generic signature " + getDeclaredGenericSignature()
  742. + " the following error was detected: " + e.getMessage());
  743. }
  744. }
  745. }
  746. }
  747. if (isGeneric()) {
  748. // update resolved typex to point at generic type not raw type.
  749. ReferenceType genericType = this.resolvedTypeX.getGenericType();
  750. // genericType.setSourceContext(this.resolvedTypeX.getSourceContext());
  751. // Can be null if unpacking whilst building the bcel delegate (in call hierarchy from BcelWorld.addSourceObjectType()
  752. // line 453) - see 317139
  753. if (genericType != null) {
  754. genericType.setStartPos(this.resolvedTypeX.getStartPos());
  755. this.resolvedTypeX = genericType;
  756. }
  757. }
  758. }
  759. public GenericSignature.FormalTypeParameter[] getAllFormals() {
  760. ensureGenericSignatureUnpacked();
  761. if (formalsForResolution == null) {
  762. return FormalTypeParameter.NONE;
  763. } else {
  764. return formalsForResolution;
  765. }
  766. }
  767. public ResolvedType getOuterClass() {
  768. if (!isNested()) {
  769. throw new IllegalStateException("Can't get the outer class of non-nested type: " + className);
  770. }
  771. // try finding outer class name from InnerClasses attribute assigned to this class
  772. for (Attribute attr : javaClass.getAttributes()) {
  773. if (attr instanceof InnerClasses) {
  774. // search for InnerClass entry that has current class as inner and some other class as outer
  775. InnerClass[] innerClss = ((InnerClasses) attr).getInnerClasses();
  776. ConstantPool cpool = javaClass.getConstantPool();
  777. for (InnerClass innerCls : innerClss) {
  778. // skip entries that miss any necessary component, 0 index means "undefined", from JVM Spec 2nd ed. par. 4.7.5
  779. if (innerCls.getInnerClassIndex() == 0 || innerCls.getOuterClassIndex() == 0) {
  780. continue;
  781. }
  782. // resolve inner class name, check if it matches current class name
  783. ConstantClass innerClsInfo = (ConstantClass) cpool.getConstant(innerCls.getInnerClassIndex());
  784. // class names in constant pool use '/' instead of '.', from JVM Spec 2nd ed. par. 4.2
  785. String innerClsName = cpool.getConstantUtf8(innerClsInfo.getNameIndex()).getValue().replace('/', '.');
  786. if (innerClsName.compareTo(className) == 0) {
  787. // resolve outer class name
  788. ConstantClass outerClsInfo = (ConstantClass) cpool.getConstant(innerCls.getOuterClassIndex());
  789. // class names in constant pool use '/' instead of '.', from JVM Spec 2nd ed. par. 4.2
  790. String outerClsName = cpool.getConstantUtf8(outerClsInfo.getNameIndex()).getValue().replace('/', '.');
  791. UnresolvedType outer = UnresolvedType.forName(outerClsName);
  792. return outer.resolve(getResolvedTypeX().getWorld());
  793. }
  794. }
  795. }
  796. }
  797. for (Attribute attr : javaClass.getAttributes()) { // bug339300
  798. ConstantPool cpool = javaClass.getConstantPool();
  799. if (attr instanceof EnclosingMethod) {
  800. EnclosingMethod enclosingMethodAttribute = (EnclosingMethod) attr;
  801. if (enclosingMethodAttribute.getEnclosingClassIndex() != 0) {
  802. ConstantClass outerClassInfo = enclosingMethodAttribute.getEnclosingClass();
  803. String outerClassName = cpool.getConstantUtf8(outerClassInfo.getNameIndex()).getValue().replace('/', '.');
  804. UnresolvedType outer = UnresolvedType.forName(outerClassName);
  805. return outer.resolve(getResolvedTypeX().getWorld());
  806. }
  807. }
  808. }
  809. // try finding outer class name by assuming standard class name mangling convention of javac for this class
  810. int lastDollar = className.lastIndexOf('$');
  811. if (lastDollar == -1) {
  812. // Is this class damaged/obfuscated? Why did we think it was nested but couldn't find the parent using
  813. // the attributes above. For now just ignore it... I wonder when ignoring this will come back to bite!
  814. return null;
  815. }
  816. String superClassName = className.substring(0, lastDollar);
  817. UnresolvedType outer = UnresolvedType.forName(superClassName);
  818. return outer.resolve(getResolvedTypeX().getWorld());
  819. }
  820. private void ensureGenericInfoProcessed() {
  821. if ((bitflag & DISCOVERED_DECLARED_SIGNATURE) != 0) {
  822. return;
  823. }
  824. bitflag |= DISCOVERED_DECLARED_SIGNATURE;
  825. Signature sigAttr = AttributeUtils.getSignatureAttribute(javaClass.getAttributes());
  826. declaredSignature = (sigAttr == null ? null : sigAttr.getSignature());
  827. if (declaredSignature != null) {
  828. isGenericType = (declaredSignature.charAt(0) == '<');
  829. }
  830. }
  831. public boolean isGeneric() {
  832. ensureGenericInfoProcessed();
  833. return isGenericType;
  834. }
  835. @Override
  836. public String toString() {
  837. return (javaClass == null ? "BcelObjectType" : "BcelObjectTypeFor:" + className);
  838. }
  839. // --- state management
  840. public void evictWeavingState() {
  841. // Can't chuck all this away
  842. if (getResolvedTypeX().getWorld().couldIncrementalCompileFollow()) {
  843. return;
  844. }
  845. if (javaClass != null) {
  846. // Force retrieval of any lazy information
  847. ensureAnnotationsUnpacked();
  848. ensureGenericInfoProcessed();
  849. getDeclaredInterfaces();
  850. getDeclaredFields();
  851. getDeclaredMethods();
  852. // The lazyClassGen is preserved for aspects - it exists to enable
  853. // around advice
  854. // inlining since the method will need 'injecting' into the affected
  855. // class. If
  856. // XnoInline is on, we can chuck away the lazyClassGen since it
  857. // won't be required
  858. // later.
  859. if (getResolvedTypeX().getWorld().isXnoInline()) {
  860. lazyClassGen = null;
  861. }
  862. // discard expensive bytecode array containing reweavable info
  863. if (weaverState != null) {
  864. weaverState.setReweavable(false);
  865. weaverState.setUnwovenClassFileData(null);
  866. }
  867. for (int i = methods.length - 1; i >= 0; i--) {
  868. methods[i].evictWeavingState();
  869. }
  870. for (int i = fields.length - 1; i >= 0; i--) {
  871. fields[i].evictWeavingState();
  872. }
  873. javaClass = null;
  874. this.artificial = true;
  875. // setSourceContext(SourceContextImpl.UNKNOWN_SOURCE_CONTEXT); //
  876. // bit naughty
  877. // interfaces=null; // force reinit - may get us the right
  878. // instances!
  879. // superClass=null;
  880. }
  881. }
  882. public void weavingCompleted() {
  883. hasBeenWoven = true;
  884. if (getResolvedTypeX().getWorld().isRunMinimalMemory()) {
  885. evictWeavingState();
  886. }
  887. if (getSourceContext() != null && !getResolvedTypeX().isAspect()) {
  888. getSourceContext().tidy();
  889. }
  890. }
  891. public boolean hasBeenWoven() {
  892. return hasBeenWoven;
  893. }
  894. @Override
  895. public boolean copySourceContext() {
  896. return false;
  897. }
  898. public void setExposedToWeaver(boolean b) {
  899. exposedToWeaver = b;
  900. }
  901. @Override
  902. public int getCompilerVersion() {
  903. return wvInfo.getMajorVersion();
  904. }
  905. public void ensureConsistent() {
  906. superTypeReference.clear();
  907. superInterfaceReferences.clear();
  908. }
  909. public boolean isWeavable() {
  910. return true;
  911. }
  912. }