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

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