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.

BcelWeaver.java 75KB

21 years ago
21 years ago
21 years ago
14 years ago
21 years ago
13 years ago
15 years ago
18 years ago
14 years ago
21 years ago
14 years ago
14 years ago
14 years ago
13 years ago
21 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
21 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
13 years ago
14 years ago
17 years ago
21 years ago
13 years ago
21 years ago
14 years ago
21 years ago
14 years ago
14 years ago
21 years ago
21 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
12 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
14 years ago
18 years ago
14 years ago
14 years ago
18 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
11 years ago
14 years ago
14 years ago
13 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
18 years ago
14 years ago
14 years ago
14 years ago
12 years ago
15 years ago
14 years ago
14 years ago
21 years ago
21 years ago
21 years ago
14 years ago
21 years ago
14 years ago
14 years ago
13 years ago
14 years ago
13 years ago
14 years ago
13 years ago
14 years ago
13 years ago
14 years ago
13 years ago
14 years ago
13 years ago
14 years ago
21 years ago
13 years ago
21 years ago
14 years ago
21 years ago
21 years ago
21 years ago
21 years ago
14 years ago
21 years ago
21 years ago
21 years ago
21 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
21 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036
  1. /* *******************************************************************
  2. * Copyright (c) 2002-2019 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. package org.aspectj.weaver.bcel;
  10. import java.io.ByteArrayInputStream;
  11. import java.io.File;
  12. import java.io.FileFilter;
  13. import java.io.FileInputStream;
  14. import java.io.FileNotFoundException;
  15. import java.io.IOException;
  16. import java.io.InputStream;
  17. import java.io.OutputStream;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.Comparator;
  22. import java.util.Enumeration;
  23. import java.util.HashMap;
  24. import java.util.HashSet;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import java.util.jar.Attributes;
  30. import java.util.jar.Attributes.Name;
  31. import java.util.jar.JarEntry;
  32. import java.util.jar.JarFile;
  33. import java.util.jar.Manifest;
  34. import java.util.zip.ZipEntry;
  35. import java.util.zip.ZipInputStream;
  36. import java.util.zip.ZipOutputStream;
  37. import org.aspectj.apache.bcel.classfile.ClassParser;
  38. import org.aspectj.apache.bcel.classfile.JavaClass;
  39. import org.aspectj.asm.AsmManager;
  40. import org.aspectj.asm.IProgramElement;
  41. import org.aspectj.asm.internal.AspectJElementHierarchy;
  42. import org.aspectj.bridge.IMessage;
  43. import org.aspectj.bridge.ISourceLocation;
  44. import org.aspectj.bridge.Message;
  45. import org.aspectj.bridge.MessageUtil;
  46. import org.aspectj.bridge.SourceLocation;
  47. import org.aspectj.bridge.WeaveMessage;
  48. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  49. import org.aspectj.bridge.context.ContextToken;
  50. import org.aspectj.util.FileUtil;
  51. import org.aspectj.util.FuzzyBoolean;
  52. import org.aspectj.weaver.Advice;
  53. import org.aspectj.weaver.AdviceKind;
  54. import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
  55. import org.aspectj.weaver.AnnotationAJ;
  56. import org.aspectj.weaver.AnnotationOnTypeMunger;
  57. import org.aspectj.weaver.BCException;
  58. import org.aspectj.weaver.CompressingDataOutputStream;
  59. import org.aspectj.weaver.ConcreteTypeMunger;
  60. import org.aspectj.weaver.CrosscuttingMembersSet;
  61. import org.aspectj.weaver.CustomMungerFactory;
  62. import org.aspectj.weaver.IClassFileProvider;
  63. import org.aspectj.weaver.IUnwovenClassFile;
  64. import org.aspectj.weaver.IWeaveRequestor;
  65. import org.aspectj.weaver.NewParentTypeMunger;
  66. import org.aspectj.weaver.ReferenceType;
  67. import org.aspectj.weaver.ReferenceTypeDelegate;
  68. import org.aspectj.weaver.ResolvedType;
  69. import org.aspectj.weaver.ResolvedTypeMunger;
  70. import org.aspectj.weaver.Shadow;
  71. import org.aspectj.weaver.ShadowMunger;
  72. import org.aspectj.weaver.UnresolvedType;
  73. import org.aspectj.weaver.WeaverMessages;
  74. import org.aspectj.weaver.WeaverStateInfo;
  75. import org.aspectj.weaver.World;
  76. import org.aspectj.weaver.model.AsmRelationshipProvider;
  77. import org.aspectj.weaver.patterns.AndPointcut;
  78. import org.aspectj.weaver.patterns.BindingPattern;
  79. import org.aspectj.weaver.patterns.BindingTypePattern;
  80. import org.aspectj.weaver.patterns.ConcreteCflowPointcut;
  81. import org.aspectj.weaver.patterns.DeclareAnnotation;
  82. import org.aspectj.weaver.patterns.DeclareParents;
  83. import org.aspectj.weaver.patterns.DeclareTypeErrorOrWarning;
  84. import org.aspectj.weaver.patterns.FastMatchInfo;
  85. import org.aspectj.weaver.patterns.IfPointcut;
  86. import org.aspectj.weaver.patterns.KindedPointcut;
  87. import org.aspectj.weaver.patterns.NameBindingPointcut;
  88. import org.aspectj.weaver.patterns.NotPointcut;
  89. import org.aspectj.weaver.patterns.OrPointcut;
  90. import org.aspectj.weaver.patterns.Pointcut;
  91. import org.aspectj.weaver.patterns.PointcutRewriter;
  92. import org.aspectj.weaver.patterns.WithinPointcut;
  93. import org.aspectj.weaver.tools.Trace;
  94. import org.aspectj.weaver.tools.TraceFactory;
  95. /**
  96. *
  97. * @author PARC
  98. * @author Andy Clement
  99. * @author Alexandre Vasseur
  100. * @author Eric Edens
  101. */
  102. public class BcelWeaver {
  103. public static final String CLOSURE_CLASS_PREFIX = "$Ajc";
  104. public static final String SYNTHETIC_CLASS_POSTFIX = "$ajc";
  105. private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelWeaver.class);
  106. private transient final BcelWorld world;
  107. private final CrosscuttingMembersSet xcutSet;
  108. private boolean inReweavableMode = false;
  109. private transient List<UnwovenClassFile> addedClasses = new ArrayList<UnwovenClassFile>();
  110. private transient List<String> deletedTypenames = new ArrayList<String>();
  111. // These four are setup by prepareForWeave
  112. private transient List<ShadowMunger> shadowMungerList = null;
  113. private transient List<ConcreteTypeMunger> typeMungerList = null;
  114. private transient List<ConcreteTypeMunger> lateTypeMungerList = null;
  115. private transient List<DeclareParents> declareParentsList = null;
  116. private Manifest manifest = null;
  117. private boolean needToReweaveWorld = false;
  118. private boolean isBatchWeave = true;
  119. private ZipOutputStream zipOutputStream;
  120. private CustomMungerFactory customMungerFactory;
  121. public BcelWeaver(BcelWorld world) {
  122. super();
  123. if (trace.isTraceEnabled()) {
  124. trace.enter("<init>", this, world);
  125. }
  126. this.world = world;
  127. this.xcutSet = world.getCrosscuttingMembersSet();
  128. if (trace.isTraceEnabled()) {
  129. trace.exit("<init>");
  130. }
  131. }
  132. /**
  133. * Add the given aspect to the weaver. The type is resolved to support DOT for static inner classes as well as DOLLAR
  134. *
  135. * @param aspectName
  136. * @return aspect
  137. */
  138. public ResolvedType addLibraryAspect(String aspectName) {
  139. if (trace.isTraceEnabled()) {
  140. trace.enter("addLibraryAspect", this, aspectName);
  141. }
  142. // 1 - resolve as is
  143. UnresolvedType unresolvedT = UnresolvedType.forName(aspectName);
  144. unresolvedT.setNeedsModifiableDelegate(true);
  145. ResolvedType type = world.resolve(unresolvedT, true);
  146. if (type.isMissing()) {
  147. // fallback on inner class lookup mechanism
  148. String fixedName = aspectName;
  149. int hasDot = fixedName.lastIndexOf('.');
  150. while (hasDot > 0) {
  151. // System.out.println("BcelWeaver.addLibraryAspect " + fixedName);
  152. char[] fixedNameChars = fixedName.toCharArray();
  153. fixedNameChars[hasDot] = '$';
  154. fixedName = new String(fixedNameChars);
  155. hasDot = fixedName.lastIndexOf('.');
  156. UnresolvedType ut = UnresolvedType.forName(fixedName);
  157. ut.setNeedsModifiableDelegate(true);
  158. type = world.resolve(ut, true);
  159. if (!type.isMissing()) {
  160. break;
  161. }
  162. }
  163. }
  164. // System.out.println("type: " + type + " for " + aspectName);
  165. if (type.isAspect()) {
  166. // Bug 119657 ensure we use the unwoven aspect
  167. WeaverStateInfo wsi = type.getWeaverState();
  168. if (wsi != null && wsi.isReweavable()) {
  169. BcelObjectType classType = getClassType(type.getName());
  170. JavaClass wovenJavaClass = classType.getJavaClass();
  171. byte[] bytes = wsi.getUnwovenClassFileData(wovenJavaClass.getBytes());
  172. JavaClass unwovenJavaClass = Utility.makeJavaClass(wovenJavaClass.getFileName(), bytes);
  173. world.storeClass(unwovenJavaClass);
  174. classType.setJavaClass(unwovenJavaClass, true);
  175. // classType.setJavaClass(Utility.makeJavaClass(classType.
  176. // getJavaClass().getFileName(),
  177. // wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes(
  178. // ))));
  179. }
  180. // TODO AV - happens to reach that a lot of time: for each type
  181. // flagged reweavable X for each aspect in the weaverstate
  182. // => mainly for nothing for LTW - pbly for something in incremental
  183. // build...
  184. xcutSet.addOrReplaceAspect(type);
  185. if (trace.isTraceEnabled()) {
  186. trace.exit("addLibraryAspect", type);
  187. }
  188. if (type.getSuperclass().isAspect()) {
  189. // If the supertype includes ITDs and the user has not included
  190. // that aspect in the aop.xml, they will
  191. // not get picked up, which can give unusual behaviour! See bug
  192. // 223094
  193. // This change causes us to pick up the super aspect regardless
  194. // of what was said in the aop.xml - giving
  195. // predictable behaviour. If the user also supplied it, there
  196. // will be no problem other than the second
  197. // addition overriding the first
  198. addLibraryAspect(type.getSuperclass().getName());
  199. }
  200. return type;
  201. } else {
  202. // FIXME AV - better warning upon no such aspect from aop.xml
  203. RuntimeException ex = new RuntimeException("Cannot register non aspect: " + type.getName() + " , " + aspectName);
  204. if (trace.isTraceEnabled()) {
  205. trace.exit("addLibraryAspect", ex);
  206. }
  207. throw ex;
  208. }
  209. }
  210. /**
  211. *
  212. * @param inFile directory containing classes or zip/jar class archive
  213. */
  214. public void addLibraryJarFile(File inFile) throws IOException {
  215. List<ResolvedType> addedAspects = null;
  216. if (inFile.isDirectory()) {
  217. addedAspects = addAspectsFromDirectory(inFile);
  218. } else {
  219. addedAspects = addAspectsFromJarFile(inFile);
  220. }
  221. for (ResolvedType addedAspect : addedAspects) {
  222. xcutSet.addOrReplaceAspect(addedAspect);
  223. }
  224. }
  225. private List<ResolvedType> addAspectsFromJarFile(File inFile) throws FileNotFoundException, IOException {
  226. ZipInputStream inStream = new ZipInputStream(new FileInputStream(inFile)); // ??? buffered
  227. List<ResolvedType> addedAspects = new ArrayList<ResolvedType>();
  228. try {
  229. while (true) {
  230. ZipEntry entry = inStream.getNextEntry();
  231. if (entry == null) {
  232. break;
  233. }
  234. if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
  235. continue;
  236. }
  237. // FIXME ASC performance? of this alternative soln.
  238. int size = (int) entry.getSize();
  239. ClassParser parser = new ClassParser(new ByteArrayInputStream(FileUtil.readAsByteArray(inStream)), entry.getName());
  240. JavaClass jc = parser.parse();
  241. inStream.closeEntry();
  242. ResolvedType type = world.addSourceObjectType(jc, false).getResolvedTypeX();
  243. type.setBinaryPath(inFile.getAbsolutePath());
  244. if (type.isAspect()) {
  245. addedAspects.add(type);
  246. } else {
  247. world.demote(type);
  248. }
  249. }
  250. } finally {
  251. inStream.close();
  252. }
  253. return addedAspects;
  254. }
  255. /**
  256. * Look for .class files that represent aspects in the supplied directory - return the list of accumulated aspects.
  257. *
  258. * @param directory the directory in which to look for Aspect .class files
  259. * @return the list of discovered aspects
  260. * @throws FileNotFoundException
  261. * @throws IOException
  262. */
  263. private List<ResolvedType> addAspectsFromDirectory(File directory) throws FileNotFoundException, IOException {
  264. List<ResolvedType> addedAspects = new ArrayList<ResolvedType>();
  265. File[] classFiles = FileUtil.listFiles(directory, new FileFilter() {
  266. public boolean accept(File pathname) {
  267. return pathname.getName().endsWith(".class");
  268. }
  269. });
  270. for (File classFile : classFiles) {
  271. FileInputStream fis = new FileInputStream(classFile);
  272. byte[] classBytes = FileUtil.readAsByteArray(fis);
  273. ResolvedType aspectType = isAspect(classBytes, classFile.getAbsolutePath(), directory);
  274. if (aspectType != null) {
  275. addedAspects.add(aspectType);
  276. }
  277. fis.close();
  278. }
  279. return addedAspects;
  280. }
  281. /**
  282. * Determine if the supplied bytes represent an aspect, if they do then create a ResolvedType instance for the aspect and return
  283. * it, otherwise return null
  284. *
  285. * @param classbytes the classbytes that might represent an aspect
  286. * @param name the name of the class
  287. * @param directory directory which contained the class file
  288. * @return a ResolvedType if the classbytes represent an aspect, otherwise null
  289. */
  290. private ResolvedType isAspect(byte[] classbytes, String name, File dir) throws IOException {
  291. ClassParser parser = new ClassParser(new ByteArrayInputStream(classbytes), name);
  292. JavaClass jc = parser.parse();
  293. ResolvedType type = world.addSourceObjectType(jc, false).getResolvedTypeX();
  294. String typeName = type.getName().replace('.', File.separatorChar);
  295. int end = name.lastIndexOf(typeName + ".class");
  296. String binaryPath = null;
  297. // if end is -1 then something weird happened, the class file is not in
  298. // the correct place, something like
  299. // bin/A.class when the declaration for A specifies it is in a package.
  300. if (end == -1) {
  301. binaryPath = dir.getAbsolutePath();
  302. } else {
  303. binaryPath = name.substring(0, end - 1);
  304. }
  305. type.setBinaryPath(binaryPath);
  306. if (type.isAspect()) {
  307. return type;
  308. } else {
  309. // immediately demote the type we just added since it will have
  310. // have been stuffed into the permanent map (assumed to be
  311. // an aspect)
  312. world.demote(type);
  313. return null;
  314. }
  315. }
  316. // // The ANT copy task should be used to copy resources across.
  317. // private final static boolean
  318. // CopyResourcesFromInpathDirectoriesToOutput=false;
  319. /**
  320. * Add any .class files in the directory to the outdir. Anything other than .class files in the directory (or its
  321. * subdirectories) are considered resources and are also copied.
  322. *
  323. */
  324. public List<UnwovenClassFile> addDirectoryContents(File inFile, File outDir) throws IOException {
  325. List<UnwovenClassFile> addedClassFiles = new ArrayList<UnwovenClassFile>();
  326. // Get a list of all files (i.e. everything that isnt a directory)
  327. File[] files = FileUtil.listFiles(inFile, new FileFilter() {
  328. public boolean accept(File f) {
  329. boolean accept = !f.isDirectory();
  330. return accept;
  331. }
  332. });
  333. // For each file, add it either as a real .class file or as a resource
  334. for (int i = 0; i < files.length; i++) {
  335. addedClassFiles.add(addClassFile(files[i], inFile, outDir));
  336. }
  337. return addedClassFiles;
  338. }
  339. /**
  340. * Adds all class files in the jar
  341. */
  342. public List<UnwovenClassFile> addJarFile(File inFile, File outDir, boolean canBeDirectory) {
  343. // System.err.println("? addJarFile(" + inFile + ", " + outDir + ")");
  344. List<UnwovenClassFile> addedClassFiles = new ArrayList<UnwovenClassFile>();
  345. needToReweaveWorld = true;
  346. JarFile inJar = null;
  347. try {
  348. // Is this a directory we are looking at?
  349. if (inFile.isDirectory() && canBeDirectory) {
  350. addedClassFiles.addAll(addDirectoryContents(inFile, outDir));
  351. } else {
  352. inJar = new JarFile(inFile);
  353. try {
  354. addManifest(inJar.getManifest());
  355. Enumeration entries = inJar.entries();
  356. while (entries.hasMoreElements()) {
  357. JarEntry entry = (JarEntry) entries.nextElement();
  358. String filename = entry.getName();
  359. String filenameLowercase = filename.toLowerCase();
  360. // Ignore class files that Java 8 won't understand (multi-release and module-info)
  361. if (filenameLowercase.startsWith("meta-inf")
  362. || filenameLowercase.endsWith("module-info.class")) {
  363. continue;
  364. }
  365. InputStream inStream = inJar.getInputStream(entry);
  366. byte[] bytes = FileUtil.readAsByteArray(inStream);
  367. // System.out.println("? addJarFile() filename='" + filename
  368. // + "'");
  369. UnwovenClassFile classFile = new UnwovenClassFile(new File(outDir, filename).getAbsolutePath(), bytes);
  370. if (filenameLowercase.endsWith(".class")) {
  371. ReferenceType type = this.addClassFile(classFile, false);
  372. StringBuffer sb = new StringBuffer();
  373. sb.append(inFile.getAbsolutePath());
  374. sb.append("!");
  375. sb.append(entry.getName());
  376. type.setBinaryPath(sb.toString());
  377. addedClassFiles.add(classFile);
  378. }
  379. // else if (!entry.isDirectory()) {
  380. //
  381. // /* bug-44190 Copy meta-data */
  382. // addResource(filename,classFile);
  383. // }
  384. inStream.close();
  385. }
  386. } finally {
  387. inJar.close();
  388. }
  389. inJar.close();
  390. }
  391. } catch (FileNotFoundException ex) {
  392. IMessage message = new Message("Could not find input jar file " + inFile.getPath() + ", ignoring", new SourceLocation(
  393. inFile, 0), false);
  394. world.getMessageHandler().handleMessage(message);
  395. } catch (IOException ex) {
  396. IMessage message = new Message("Could not read input jar file " + inFile.getPath() + "(" + ex.getMessage() + ")",
  397. new SourceLocation(inFile, 0), true);
  398. world.getMessageHandler().handleMessage(message);
  399. } finally {
  400. if (inJar != null) {
  401. try {
  402. inJar.close();
  403. } catch (IOException ex) {
  404. IMessage message = new Message("Could not close input jar file " + inFile.getPath() + "(" + ex.getMessage()
  405. + ")", new SourceLocation(inFile, 0), true);
  406. world.getMessageHandler().handleMessage(message);
  407. }
  408. }
  409. }
  410. return addedClassFiles;
  411. }
  412. public boolean needToReweaveWorld() {
  413. return needToReweaveWorld;
  414. }
  415. /**
  416. * Should be addOrReplace
  417. */
  418. public ReferenceType addClassFile(UnwovenClassFile classFile, boolean fromInpath) {
  419. addedClasses.add(classFile);
  420. ReferenceType type = world.addSourceObjectType(classFile.getJavaClass(), false).getResolvedTypeX();
  421. if (fromInpath) {
  422. type.setBinaryPath(classFile.getFilename());
  423. }
  424. return type;
  425. }
  426. public UnwovenClassFile addClassFile(File classFile, File inPathDir, File outDir) throws IOException {
  427. FileInputStream fis = new FileInputStream(classFile);
  428. byte[] bytes = FileUtil.readAsByteArray(fis);
  429. // String relativePath = files[i].getPath();
  430. // ASSERT:
  431. // files[i].getAbsolutePath().startsWith(inFile.getAbsolutePath()
  432. // or we are in trouble...
  433. String filename = classFile.getAbsolutePath().substring(inPathDir.getAbsolutePath().length() + 1);
  434. UnwovenClassFile ucf = new UnwovenClassFile(new File(outDir, filename).getAbsolutePath(), bytes);
  435. if (filename.endsWith(".class")) {
  436. // System.err.println(
  437. // "BCELWeaver: processing class from input directory "+classFile);
  438. StringBuffer sb = new StringBuffer();
  439. sb.append(inPathDir.getAbsolutePath());
  440. sb.append("!");
  441. sb.append(filename);
  442. ReferenceType type = this.addClassFile(ucf, false);
  443. type.setBinaryPath(sb.toString());
  444. }
  445. fis.close();
  446. return ucf;
  447. }
  448. public void deleteClassFile(String typename) {
  449. deletedTypenames.add(typename);
  450. world.deleteSourceObjectType(UnresolvedType.forName(typename));
  451. }
  452. // ---- weave preparation
  453. public void setIsBatchWeave(boolean b) {
  454. isBatchWeave = b;
  455. }
  456. public void prepareForWeave() {
  457. if (trace.isTraceEnabled()) {
  458. trace.enter("prepareForWeave", this);
  459. }
  460. needToReweaveWorld = xcutSet.hasChangedSinceLastReset();
  461. // update mungers
  462. for (Iterator<UnwovenClassFile> i = addedClasses.iterator(); i.hasNext();) {
  463. UnwovenClassFile jc = i.next();
  464. String name = jc.getClassName();
  465. ResolvedType type = world.resolve(name);
  466. // No overweaving guard. If you have one then when overweaving is on the
  467. // addOrReplaceAspect will not be called when the aspect delegate changes from
  468. // EclipseSourceType to BcelObjectType. This will mean the mungers
  469. // are not picked up.
  470. if (type.isAspect()) {
  471. needToReweaveWorld |= xcutSet.addOrReplaceAspect(type);
  472. }
  473. }
  474. for (Iterator<String> i = deletedTypenames.iterator(); i.hasNext();) {
  475. String name = i.next();
  476. if (xcutSet.deleteAspect(UnresolvedType.forName(name))) {
  477. needToReweaveWorld = true;
  478. }
  479. }
  480. shadowMungerList = xcutSet.getShadowMungers();
  481. // world.debug("shadow mungers=" + shadowMungerList);
  482. rewritePointcuts(shadowMungerList);
  483. // Sometimes an error occurs during rewriting pointcuts (for example, if
  484. // ambiguous bindings
  485. // are detected) - we ought to fail the prepare when this happens
  486. // because continuing with
  487. // inconsistent pointcuts could lead to problems
  488. typeMungerList = xcutSet.getTypeMungers();
  489. lateTypeMungerList = xcutSet.getLateTypeMungers();
  490. declareParentsList = xcutSet.getDeclareParents();
  491. addCustomMungers();
  492. // The ordering here used to be based on a string compare on toString()
  493. // for the two mungers -
  494. // that breaks for the @AJ style where advice names aren't
  495. // programmatically generated. So we
  496. // have changed the sorting to be based on source location in the file -
  497. // this is reliable, in
  498. // the case of source locations missing, we assume they are 'sorted' -
  499. // i.e. the order in
  500. // which they were added to the collection is correct, this enables the
  501. // @AJ stuff to work properly.
  502. // When @AJ processing starts filling in source locations for mungers,
  503. // this code may need
  504. // a bit of alteration...
  505. Collections.sort(shadowMungerList, new Comparator<ShadowMunger>() {
  506. public int compare(ShadowMunger sm1, ShadowMunger sm2) {
  507. if (sm1.getSourceLocation() == null) {
  508. return (sm2.getSourceLocation() == null ? 0 : 1);
  509. }
  510. if (sm2.getSourceLocation() == null) {
  511. return -1;
  512. }
  513. return (sm2.getSourceLocation().getOffset() - sm1.getSourceLocation().getOffset());
  514. }
  515. });
  516. if (inReweavableMode) {
  517. world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.REWEAVABLE_MODE), null, null);
  518. }
  519. if (trace.isTraceEnabled()) {
  520. trace.exit("prepareForWeave");
  521. }
  522. }
  523. private void addCustomMungers() {
  524. if (customMungerFactory != null) {
  525. for (Iterator<UnwovenClassFile> i = addedClasses.iterator(); i.hasNext();) {
  526. UnwovenClassFile jc = i.next();
  527. String name = jc.getClassName();
  528. ResolvedType type = world.resolve(name);
  529. if (type.isAspect()) {
  530. Collection<ShadowMunger> shadowMungers = customMungerFactory.createCustomShadowMungers(type);
  531. if (shadowMungers != null) {
  532. shadowMungerList.addAll(shadowMungers);
  533. }
  534. Collection<ConcreteTypeMunger> typeMungers = customMungerFactory.createCustomTypeMungers(type);
  535. if (typeMungers != null) {
  536. typeMungerList.addAll(typeMungers);
  537. }
  538. }
  539. }
  540. }
  541. }
  542. public void setCustomMungerFactory(CustomMungerFactory factory) {
  543. customMungerFactory = factory;
  544. }
  545. /*
  546. * Rewrite all of the pointcuts in the world into their most efficient form for subsequent matching. Also ensure that if
  547. * pc1.equals(pc2) then pc1 == pc2 (for non-binding pcds) by making references all point to the same instance. Since pointcuts
  548. * remember their match decision on the last shadow, this makes matching faster when many pointcuts share common elements, or
  549. * even when one single pointcut has one common element (which can be a side-effect of DNF rewriting).
  550. */
  551. private void rewritePointcuts(List<ShadowMunger> shadowMungers) {
  552. PointcutRewriter rewriter = new PointcutRewriter();
  553. for (ShadowMunger munger : shadowMungers) {
  554. Pointcut p = munger.getPointcut();
  555. Pointcut newP = rewriter.rewrite(p);
  556. // validateBindings now whilst we still have around the pointcut
  557. // that resembles what the user actually wrote in their program
  558. // text.
  559. if (munger instanceof Advice) {
  560. Advice advice = (Advice) munger;
  561. if (advice.getSignature() != null) {
  562. final int numFormals;
  563. final String names[];
  564. // If the advice is being concretized in a @AJ aspect *and*
  565. // the advice was declared in
  566. // an @AJ aspect (it could have been inherited from a code
  567. // style aspect) then
  568. // evaluate the alternative set of formals. pr125699
  569. if ((advice.getConcreteAspect().isAnnotationStyleAspect() && advice.getDeclaringAspect() != null && advice
  570. .getDeclaringAspect().resolve(world).isAnnotationStyleAspect())
  571. || advice.isAnnotationStyle()) {
  572. numFormals = advice.getBaseParameterCount();
  573. int numArgs = advice.getSignature().getParameterTypes().length;
  574. if (numFormals > 0) {
  575. names = advice.getSignature().getParameterNames(world);
  576. validateBindings(newP, p, numArgs, names);
  577. }
  578. } else {
  579. numFormals = advice.getBaseParameterCount();
  580. if (numFormals > 0) {
  581. names = advice.getBaseParameterNames(world);
  582. validateBindings(newP, p, numFormals, names);
  583. }
  584. }
  585. }
  586. }
  587. newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames;
  588. munger.setPointcut(newP);
  589. }
  590. // now that we have optimized individual pointcuts, optimize
  591. // across the set of pointcuts....
  592. // Use a map from key based on pc equality, to value based on
  593. // pc identity.
  594. Map<Pointcut, Pointcut> pcMap = new HashMap<Pointcut, Pointcut>();
  595. for (ShadowMunger munger: shadowMungers) {
  596. Pointcut p = munger.getPointcut();
  597. Pointcut newP = shareEntriesFromMap(p, pcMap);
  598. newP.m_ignoreUnboundBindingForNames = p.m_ignoreUnboundBindingForNames;
  599. munger.setPointcut(newP);
  600. }
  601. }
  602. private Pointcut shareEntriesFromMap(Pointcut p, Map<Pointcut, Pointcut> pcMap) {
  603. // some things cant be shared...
  604. if (p instanceof NameBindingPointcut) {
  605. return p;
  606. }
  607. if (p instanceof IfPointcut) {
  608. return p;
  609. }
  610. if (p instanceof ConcreteCflowPointcut) {
  611. return p;
  612. }
  613. if (p instanceof AndPointcut) {
  614. AndPointcut apc = (AndPointcut) p;
  615. Pointcut left = shareEntriesFromMap(apc.getLeft(), pcMap);
  616. Pointcut right = shareEntriesFromMap(apc.getRight(), pcMap);
  617. return new AndPointcut(left, right);
  618. } else if (p instanceof OrPointcut) {
  619. OrPointcut opc = (OrPointcut) p;
  620. Pointcut left = shareEntriesFromMap(opc.getLeft(), pcMap);
  621. Pointcut right = shareEntriesFromMap(opc.getRight(), pcMap);
  622. return new OrPointcut(left, right);
  623. } else if (p instanceof NotPointcut) {
  624. NotPointcut npc = (NotPointcut) p;
  625. Pointcut not = shareEntriesFromMap(npc.getNegatedPointcut(), pcMap);
  626. return new NotPointcut(not);
  627. } else {
  628. // primitive pcd
  629. if (pcMap.containsKey(p)) { // based on equality
  630. return pcMap.get(p); // same instance (identity)
  631. } else {
  632. pcMap.put(p, p);
  633. return p;
  634. }
  635. }
  636. }
  637. // userPointcut is the pointcut that the user wrote in the program text.
  638. // dnfPointcut is the same pointcut rewritten in DNF
  639. // numFormals is the number of formal parameters in the pointcut
  640. // if numFormals > 0 then every branch of a disjunction must bind each
  641. // formal once and only once.
  642. // in addition, the left and right branches of a disjunction must hold on
  643. // join point kinds in
  644. // common.
  645. private void validateBindings(Pointcut dnfPointcut, Pointcut userPointcut, int numFormals, String[] names) {
  646. if (numFormals == 0) {
  647. return; // nothing to check
  648. }
  649. if (dnfPointcut.couldMatchKinds() == Shadow.NO_SHADOW_KINDS_BITS) {
  650. return; // cant have problems if you dont match!
  651. }
  652. if (dnfPointcut instanceof OrPointcut) {
  653. OrPointcut orBasedDNFPointcut = (OrPointcut) dnfPointcut;
  654. Pointcut[] leftBindings = new Pointcut[numFormals];
  655. Pointcut[] rightBindings = new Pointcut[numFormals];
  656. validateOrBranch(orBasedDNFPointcut, userPointcut, numFormals, names, leftBindings, rightBindings);
  657. } else {
  658. Pointcut[] bindings = new Pointcut[numFormals];
  659. validateSingleBranch(dnfPointcut, userPointcut, numFormals, names, bindings);
  660. }
  661. }
  662. private void validateOrBranch(OrPointcut pc, Pointcut userPointcut, int numFormals, String[] names, Pointcut[] leftBindings,
  663. Pointcut[] rightBindings) {
  664. Pointcut left = pc.getLeft();
  665. Pointcut right = pc.getRight();
  666. if (left instanceof OrPointcut) {
  667. Pointcut[] newRightBindings = new Pointcut[numFormals];
  668. validateOrBranch((OrPointcut) left, userPointcut, numFormals, names, leftBindings, newRightBindings);
  669. } else {
  670. if (left.couldMatchKinds() != Shadow.NO_SHADOW_KINDS_BITS) {
  671. validateSingleBranch(left, userPointcut, numFormals, names, leftBindings);
  672. }
  673. }
  674. if (right instanceof OrPointcut) {
  675. Pointcut[] newLeftBindings = new Pointcut[numFormals];
  676. validateOrBranch((OrPointcut) right, userPointcut, numFormals, names, newLeftBindings, rightBindings);
  677. } else {
  678. if (right.couldMatchKinds() != Shadow.NO_SHADOW_KINDS_BITS) {
  679. validateSingleBranch(right, userPointcut, numFormals, names, rightBindings);
  680. }
  681. }
  682. int kindsInCommon = left.couldMatchKinds() & right.couldMatchKinds();
  683. if (kindsInCommon != Shadow.NO_SHADOW_KINDS_BITS && couldEverMatchSameJoinPoints(left, right)) {
  684. // we know that every branch binds every formal, so there is no
  685. // ambiguity
  686. // if each branch binds it in exactly the same way...
  687. List<String> ambiguousNames = new ArrayList<String>();
  688. for (int i = 0; i < numFormals; i++) {
  689. if (leftBindings[i] == null) {
  690. if (rightBindings[i] != null) {
  691. ambiguousNames.add(names[i]);
  692. }
  693. } else if (!leftBindings[i].equals(rightBindings[i])) {
  694. ambiguousNames.add(names[i]);
  695. }
  696. }
  697. if (!ambiguousNames.isEmpty()) {
  698. raiseAmbiguityInDisjunctionError(userPointcut, ambiguousNames);
  699. }
  700. }
  701. }
  702. // pc is a pointcut that does not contain any disjunctions
  703. // check that every formal is bound (negation doesn't count).
  704. // we know that numFormals > 0 or else we would not be called
  705. private void validateSingleBranch(Pointcut pc, Pointcut userPointcut, int numFormals, String[] names, Pointcut[] bindings) {
  706. boolean[] foundFormals = new boolean[numFormals];
  707. for (int i = 0; i < foundFormals.length; i++) {
  708. foundFormals[i] = false;
  709. }
  710. validateSingleBranchRecursion(pc, userPointcut, foundFormals, names, bindings);
  711. for (int i = 0; i < foundFormals.length; i++) {
  712. if (!foundFormals[i]) {
  713. boolean ignore = false;
  714. // ATAJ soften the unbound error for implicit bindings like
  715. // JoinPoint in @AJ style
  716. for (int j = 0; j < userPointcut.m_ignoreUnboundBindingForNames.length; j++) {
  717. if (names[i] != null && names[i].equals(userPointcut.m_ignoreUnboundBindingForNames[j])) {
  718. ignore = true;
  719. break;
  720. }
  721. }
  722. if (!ignore) {
  723. raiseUnboundFormalError(names[i], userPointcut);
  724. }
  725. }
  726. }
  727. }
  728. // each formal must appear exactly once
  729. private void validateSingleBranchRecursion(Pointcut pc, Pointcut userPointcut, boolean[] foundFormals, String[] names,
  730. Pointcut[] bindings) {
  731. if (pc instanceof NotPointcut) {
  732. // nots can only appear at leaves in DNF
  733. NotPointcut not = (NotPointcut) pc;
  734. if (not.getNegatedPointcut() instanceof NameBindingPointcut) {
  735. NameBindingPointcut nnbp = (NameBindingPointcut) not.getNegatedPointcut();
  736. if (!nnbp.getBindingAnnotationTypePatterns().isEmpty() && !nnbp.getBindingTypePatterns().isEmpty()) {
  737. raiseNegationBindingError(userPointcut);
  738. }
  739. }
  740. } else if (pc instanceof AndPointcut) {
  741. AndPointcut and = (AndPointcut) pc;
  742. validateSingleBranchRecursion(and.getLeft(), userPointcut, foundFormals, names, bindings);
  743. validateSingleBranchRecursion(and.getRight(), userPointcut, foundFormals, names, bindings);
  744. } else if (pc instanceof NameBindingPointcut) {
  745. List/* BindingTypePattern */btps = ((NameBindingPointcut) pc).getBindingTypePatterns();
  746. for (Iterator iter = btps.iterator(); iter.hasNext();) {
  747. BindingTypePattern btp = (BindingTypePattern) iter.next();
  748. int index = btp.getFormalIndex();
  749. bindings[index] = pc;
  750. if (foundFormals[index]) {
  751. raiseAmbiguousBindingError(names[index], userPointcut);
  752. } else {
  753. foundFormals[index] = true;
  754. }
  755. }
  756. List/* BindingPattern */baps = ((NameBindingPointcut) pc).getBindingAnnotationTypePatterns();
  757. for (Iterator iter = baps.iterator(); iter.hasNext();) {
  758. BindingPattern bap = (BindingPattern) iter.next();
  759. int index = bap.getFormalIndex();
  760. bindings[index] = pc;
  761. if (foundFormals[index]) {
  762. raiseAmbiguousBindingError(names[index], userPointcut);
  763. } else {
  764. foundFormals[index] = true;
  765. }
  766. }
  767. } else if (pc instanceof ConcreteCflowPointcut) {
  768. ConcreteCflowPointcut cfp = (ConcreteCflowPointcut) pc;
  769. int[] slots = cfp.getUsedFormalSlots();
  770. for (int i = 0; i < slots.length; i++) {
  771. bindings[slots[i]] = cfp;
  772. if (foundFormals[slots[i]]) {
  773. raiseAmbiguousBindingError(names[slots[i]], userPointcut);
  774. } else {
  775. foundFormals[slots[i]] = true;
  776. }
  777. }
  778. }
  779. }
  780. // By returning false from this method, we are allowing binding of the same
  781. // variable on either side of an or.
  782. // Be conservative :- have to consider overriding, varargs, autoboxing,
  783. // the effects of itds (on within for example), interfaces, the fact that
  784. // join points can have multiple signatures and so on.
  785. private boolean couldEverMatchSameJoinPoints(Pointcut left, Pointcut right) {
  786. if (left instanceof OrPointcut) {
  787. OrPointcut leftOrPointcut = (OrPointcut) left;
  788. if (couldEverMatchSameJoinPoints(leftOrPointcut.getLeft(), right)) {
  789. return true;
  790. }
  791. if (couldEverMatchSameJoinPoints(leftOrPointcut.getRight(), right)) {
  792. return true;
  793. }
  794. return false;
  795. }
  796. if (right instanceof OrPointcut) {
  797. OrPointcut rightOrPointcut = (OrPointcut) right;
  798. if (couldEverMatchSameJoinPoints(left, rightOrPointcut.getLeft())) {
  799. return true;
  800. }
  801. if (couldEverMatchSameJoinPoints(left, rightOrPointcut.getRight())) {
  802. return true;
  803. }
  804. return false;
  805. }
  806. // look for withins
  807. WithinPointcut leftWithin = (WithinPointcut) findFirstPointcutIn(left, WithinPointcut.class);
  808. WithinPointcut rightWithin = (WithinPointcut) findFirstPointcutIn(right, WithinPointcut.class);
  809. if ((leftWithin != null) && (rightWithin != null)) {
  810. if (!leftWithin.couldEverMatchSameJoinPointsAs(rightWithin)) {
  811. return false;
  812. }
  813. }
  814. // look for kinded
  815. KindedPointcut leftKind = (KindedPointcut) findFirstPointcutIn(left, KindedPointcut.class);
  816. KindedPointcut rightKind = (KindedPointcut) findFirstPointcutIn(right, KindedPointcut.class);
  817. if ((leftKind != null) && (rightKind != null)) {
  818. if (!leftKind.couldEverMatchSameJoinPointsAs(rightKind)) {
  819. return false;
  820. }
  821. }
  822. return true;
  823. }
  824. private Pointcut findFirstPointcutIn(Pointcut toSearch, Class toLookFor) {
  825. if (toSearch instanceof NotPointcut) {
  826. return null;
  827. }
  828. if (toLookFor.isInstance(toSearch)) {
  829. return toSearch;
  830. }
  831. if (toSearch instanceof AndPointcut) {
  832. AndPointcut apc = (AndPointcut) toSearch;
  833. Pointcut left = findFirstPointcutIn(apc.getLeft(), toLookFor);
  834. if (left != null) {
  835. return left;
  836. }
  837. return findFirstPointcutIn(apc.getRight(), toLookFor);
  838. }
  839. return null;
  840. }
  841. /**
  842. * @param userPointcut
  843. */
  844. private void raiseNegationBindingError(Pointcut userPointcut) {
  845. world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.NEGATION_DOESNT_ALLOW_BINDING), userPointcut
  846. .getSourceContext().makeSourceLocation(userPointcut), null);
  847. }
  848. /**
  849. * @param name
  850. * @param userPointcut
  851. */
  852. private void raiseAmbiguousBindingError(String name, Pointcut userPointcut) {
  853. world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.AMBIGUOUS_BINDING, name), userPointcut
  854. .getSourceContext().makeSourceLocation(userPointcut), null);
  855. }
  856. /**
  857. * @param userPointcut
  858. */
  859. private void raiseAmbiguityInDisjunctionError(Pointcut userPointcut, List<String> names) {
  860. StringBuffer formalNames = new StringBuffer(names.get(0).toString());
  861. for (int i = 1; i < names.size(); i++) {
  862. formalNames.append(", ");
  863. formalNames.append(names.get(i));
  864. }
  865. world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.AMBIGUOUS_BINDING_IN_OR, formalNames), userPointcut
  866. .getSourceContext().makeSourceLocation(userPointcut), null);
  867. }
  868. /**
  869. * @param name
  870. * @param userPointcut
  871. */
  872. private void raiseUnboundFormalError(String name, Pointcut userPointcut) {
  873. world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.UNBOUND_FORMAL, name),
  874. userPointcut.getSourceLocation(), null);
  875. }
  876. public void addManifest(Manifest newManifest) {
  877. // System.out.println("? addManifest() newManifest=" + newManifest);
  878. if (manifest == null) {
  879. manifest = newManifest;
  880. }
  881. }
  882. public Manifest getManifest(boolean shouldCreate) {
  883. if (manifest == null && shouldCreate) {
  884. String WEAVER_MANIFEST_VERSION = "1.0";
  885. Attributes.Name CREATED_BY = new Name("Created-By");
  886. String WEAVER_CREATED_BY = "AspectJ Compiler";
  887. manifest = new Manifest();
  888. Attributes attributes = manifest.getMainAttributes();
  889. attributes.put(Name.MANIFEST_VERSION, WEAVER_MANIFEST_VERSION);
  890. attributes.put(CREATED_BY, WEAVER_CREATED_BY);
  891. }
  892. return manifest;
  893. }
  894. // ---- weaving
  895. // FOR TESTING
  896. public Collection<String> weave(File file) throws IOException {
  897. OutputStream os = FileUtil.makeOutputStream(file);
  898. this.zipOutputStream = new ZipOutputStream(os);
  899. prepareForWeave();
  900. Collection<String> c = weave(new IClassFileProvider() {
  901. public boolean isApplyAtAspectJMungersOnly() {
  902. return false;
  903. }
  904. public Iterator<UnwovenClassFile> getClassFileIterator() {
  905. return addedClasses.iterator();
  906. }
  907. public IWeaveRequestor getRequestor() {
  908. return new IWeaveRequestor() {
  909. public void acceptResult(IUnwovenClassFile result) {
  910. try {
  911. writeZipEntry(result.getFilename(), result.getBytes());
  912. } catch (IOException ex) {
  913. }
  914. }
  915. public void processingReweavableState() {
  916. }
  917. public void addingTypeMungers() {
  918. }
  919. public void weavingAspects() {
  920. }
  921. public void weavingClasses() {
  922. }
  923. public void weaveCompleted() {
  924. }
  925. };
  926. }
  927. });
  928. // /* BUG 40943*/
  929. // dumpResourcesToOutJar();
  930. zipOutputStream.close(); // this flushes and closes the acutal file
  931. return c;
  932. }
  933. private Set<IProgramElement> candidatesForRemoval = null;
  934. // variation of "weave" that sources class files from an external source.
  935. public Collection<String> weave(IClassFileProvider input) throws IOException {
  936. if (trace.isTraceEnabled()) {
  937. trace.enter("weave", this, input);
  938. }
  939. ContextToken weaveToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING, "");
  940. Collection<String> wovenClassNames = new ArrayList<String>();
  941. IWeaveRequestor requestor = input.getRequestor();
  942. if (world.getModel() != null && world.isMinimalModel()) {
  943. candidatesForRemoval = new HashSet<IProgramElement>();
  944. }
  945. if (world.getModel() != null && !isBatchWeave) {
  946. AsmManager manager = world.getModelAsAsmManager();
  947. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  948. UnwovenClassFile classFile = i.next();
  949. // remove all relationships where this file being woven is
  950. // the target of the relationship
  951. manager.removeRelationshipsTargettingThisType(classFile.getClassName());
  952. }
  953. }
  954. // Go through the types and ensure any 'damaged' during compile time are
  955. // repaired prior to weaving
  956. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  957. UnwovenClassFile classFile = i.next();
  958. String className = classFile.getClassName();
  959. ResolvedType theType = world.resolve(className);
  960. if (theType != null) {
  961. theType.ensureConsistent();
  962. }
  963. }
  964. // special case for AtAspectJMungerOnly - see #113587
  965. if (input.isApplyAtAspectJMungersOnly()) {
  966. ContextToken atAspectJMungersOnly = CompilationAndWeavingContext.enteringPhase(
  967. CompilationAndWeavingContext.PROCESSING_ATASPECTJTYPE_MUNGERS_ONLY, "");
  968. requestor.weavingAspects();
  969. // ContextToken aspectToken =
  970. CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_ASPECTS, "");
  971. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  972. UnwovenClassFile classFile = i.next();
  973. String className = classFile.getClassName();
  974. ResolvedType theType = world.resolve(className);
  975. if (theType.isAnnotationStyleAspect()) {
  976. BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
  977. if (classType == null) {
  978. throw new BCException("Can't find bcel delegate for " + className + " type=" + theType.getClass());
  979. }
  980. LazyClassGen clazz = classType.getLazyClassGen();
  981. BcelPerClauseAspectAdder selfMunger = new BcelPerClauseAspectAdder(theType, theType.getPerClause().getKind());
  982. selfMunger.forceMunge(clazz, true);
  983. classType.finishedWith();
  984. UnwovenClassFile[] newClasses = getClassFilesFor(clazz);
  985. for (int news = 0; news < newClasses.length; news++) {
  986. requestor.acceptResult(newClasses[news]);
  987. }
  988. wovenClassNames.add(classFile.getClassName());
  989. }
  990. }
  991. requestor.weaveCompleted();
  992. CompilationAndWeavingContext.leavingPhase(atAspectJMungersOnly);
  993. return wovenClassNames;
  994. }
  995. requestor.processingReweavableState();
  996. ContextToken reweaveToken = CompilationAndWeavingContext.enteringPhase(
  997. CompilationAndWeavingContext.PROCESSING_REWEAVABLE_STATE, "");
  998. prepareToProcessReweavableState();
  999. // clear all state from files we'll be reweaving
  1000. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  1001. UnwovenClassFile classFile = i.next();
  1002. String className = classFile.getClassName();
  1003. BcelObjectType classType = getClassType(className);
  1004. // null return from getClassType() means the delegate is an eclipse
  1005. // source type - so
  1006. // there *cant* be any reweavable state... (he bravely claimed...)
  1007. if (classType != null) {
  1008. ContextToken tok = CompilationAndWeavingContext.enteringPhase(
  1009. CompilationAndWeavingContext.PROCESSING_REWEAVABLE_STATE, className);
  1010. processReweavableStateIfPresent(className, classType);
  1011. CompilationAndWeavingContext.leavingPhase(tok);
  1012. }
  1013. }
  1014. CompilationAndWeavingContext.leavingPhase(reweaveToken);
  1015. ContextToken typeMungingToken = CompilationAndWeavingContext.enteringPhase(
  1016. CompilationAndWeavingContext.PROCESSING_TYPE_MUNGERS, "");
  1017. requestor.addingTypeMungers();
  1018. // We process type mungers in two groups, first mungers that change the
  1019. // type
  1020. // hierarchy, then 'normal' ITD type mungers.
  1021. // Process the types in a predictable order (rather than the order
  1022. // encountered).
  1023. // For class A, the order is superclasses of A then superinterfaces of A
  1024. // (and this mechanism is applied recursively)
  1025. List<String> typesToProcess = new ArrayList<String>();
  1026. for (Iterator<UnwovenClassFile> iter = input.getClassFileIterator(); iter.hasNext();) {
  1027. UnwovenClassFile clf = iter.next();
  1028. typesToProcess.add(clf.getClassName());
  1029. }
  1030. while (typesToProcess.size() > 0) {
  1031. weaveParentsFor(typesToProcess, typesToProcess.get(0), null);
  1032. }
  1033. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  1034. UnwovenClassFile classFile = i.next();
  1035. String className = classFile.getClassName();
  1036. addNormalTypeMungers(className);
  1037. }
  1038. CompilationAndWeavingContext.leavingPhase(typeMungingToken);
  1039. requestor.weavingAspects();
  1040. ContextToken aspectToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_ASPECTS, "");
  1041. // first weave into aspects
  1042. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  1043. UnwovenClassFile classFile = i.next();
  1044. String className = classFile.getClassName();
  1045. ResolvedType theType = world.resolve(className);
  1046. if (theType.isAspect()) {
  1047. BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
  1048. if (classType == null) {
  1049. // Sometimes.. if the Bcel Delegate couldn't be found then a
  1050. // problem occurred at compile time - on
  1051. // a previous compiler run. In this case I assert the
  1052. // delegate will still be an EclipseSourceType
  1053. // and we can ignore the problem here (the original compile
  1054. // error will be reported again from
  1055. // the eclipse source type) - pr113531
  1056. ReferenceTypeDelegate theDelegate = ((ReferenceType) theType).getDelegate();
  1057. if (theDelegate.getClass().getName().endsWith("EclipseSourceType")) {
  1058. continue;
  1059. }
  1060. throw new BCException("Can't find bcel delegate for " + className + " type=" + theType.getClass());
  1061. }
  1062. weaveAndNotify(classFile, classType, requestor);
  1063. wovenClassNames.add(className);
  1064. }
  1065. }
  1066. CompilationAndWeavingContext.leavingPhase(aspectToken);
  1067. requestor.weavingClasses();
  1068. ContextToken classToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_CLASSES, "");
  1069. // then weave into non-aspects
  1070. for (Iterator<UnwovenClassFile> i = input.getClassFileIterator(); i.hasNext();) {
  1071. UnwovenClassFile classFile = i.next();
  1072. String className = classFile.getClassName();
  1073. ResolvedType theType = world.resolve(className);
  1074. if (!theType.isAspect()) {
  1075. BcelObjectType classType = BcelWorld.getBcelObjectType(theType);
  1076. if (classType == null) {
  1077. // bug 119882 - see above comment for bug 113531
  1078. ReferenceTypeDelegate theDelegate = ((ReferenceType) theType).getDelegate();
  1079. // TODO urgh - put a method on the interface to check this,
  1080. // string compare is hideous
  1081. if (theDelegate.getClass().getName().endsWith("EclipseSourceType")) {
  1082. continue;
  1083. }
  1084. throw new BCException("Can't find bcel delegate for " + className + " type=" + theType.getClass());
  1085. }
  1086. weaveAndNotify(classFile, classType, requestor);
  1087. wovenClassNames.add(className);
  1088. }
  1089. }
  1090. CompilationAndWeavingContext.leavingPhase(classToken);
  1091. addedClasses.clear();
  1092. deletedTypenames.clear();
  1093. requestor.weaveCompleted();
  1094. CompilationAndWeavingContext.leavingPhase(weaveToken);
  1095. if (trace.isTraceEnabled()) {
  1096. trace.exit("weave", wovenClassNames);
  1097. }
  1098. if (world.getModel() != null && world.isMinimalModel()) {
  1099. candidatesForRemoval.clear();
  1100. }
  1101. return wovenClassNames;
  1102. }
  1103. public void allWeavingComplete() {
  1104. warnOnUnmatchedAdvice();
  1105. }
  1106. /**
  1107. * In 1.5 mode and with XLint:adviceDidNotMatch enabled, put out messages for any mungers that did not match anything.
  1108. */
  1109. private void warnOnUnmatchedAdvice() {
  1110. class AdviceLocation {
  1111. private final int lineNo;
  1112. private final UnresolvedType inAspect;
  1113. public AdviceLocation(BcelAdvice advice) {
  1114. this.lineNo = advice.getSourceLocation().getLine();
  1115. this.inAspect = advice.getDeclaringAspect();
  1116. }
  1117. @Override
  1118. public boolean equals(Object obj) {
  1119. if (!(obj instanceof AdviceLocation)) {
  1120. return false;
  1121. }
  1122. AdviceLocation other = (AdviceLocation) obj;
  1123. if (this.lineNo != other.lineNo) {
  1124. return false;
  1125. }
  1126. if (!this.inAspect.equals(other.inAspect)) {
  1127. return false;
  1128. }
  1129. return true;
  1130. }
  1131. @Override
  1132. public int hashCode() {
  1133. return 37 + 17 * lineNo + 17 * inAspect.hashCode();
  1134. }
  1135. }
  1136. // FIXME asc Should be factored out into Xlint code and done
  1137. // automatically for all xlint messages, ideally.
  1138. // if a piece of advice hasn't matched anywhere and we are in -1.5 mode,
  1139. // put out a warning
  1140. if (world.isInJava5Mode() && world.getLint().adviceDidNotMatch.isEnabled()) {
  1141. List l = world.getCrosscuttingMembersSet().getShadowMungers();
  1142. Set<AdviceLocation> alreadyWarnedLocations = new HashSet<AdviceLocation>();
  1143. for (Iterator iter = l.iterator(); iter.hasNext();) {
  1144. ShadowMunger element = (ShadowMunger) iter.next();
  1145. // This will stop us incorrectly reporting deow checkers:
  1146. if (element instanceof BcelAdvice) {
  1147. BcelAdvice ba = (BcelAdvice) element;
  1148. if (ba.getKind() == AdviceKind.CflowEntry || ba.getKind() == AdviceKind.CflowBelowEntry) {
  1149. continue;
  1150. }
  1151. if (!ba.hasMatchedSomething()) {
  1152. // Because we implement some features of AJ itself by
  1153. // creating our own kind of mungers, you sometimes
  1154. // find that ba.getSignature() is not a BcelMethod - for
  1155. // example it might be a cflow entry munger.
  1156. if (ba.getSignature() != null) {
  1157. // check we haven't already warned on this advice and line
  1158. // (cflow creates multiple mungers for the same advice)
  1159. AdviceLocation loc = new AdviceLocation(ba);
  1160. if (alreadyWarnedLocations.contains(loc)) {
  1161. continue;
  1162. } else {
  1163. alreadyWarnedLocations.add(loc);
  1164. }
  1165. if (!(ba.getSignature() instanceof BcelMethod)
  1166. || !Utility.isSuppressing(ba.getSignature(), "adviceDidNotMatch")) {
  1167. world.getLint().adviceDidNotMatch.signal(ba.getDeclaringAspect().toString(), new SourceLocation(
  1168. element.getSourceLocation().getSourceFile(), element.getSourceLocation().getLine()));
  1169. }
  1170. }
  1171. }
  1172. }
  1173. }
  1174. }
  1175. }
  1176. /**
  1177. * 'typeToWeave' is one from the 'typesForWeaving' list. This routine ensures we process supertypes (classes/interfaces) of
  1178. * 'typeToWeave' that are in the 'typesForWeaving' list before 'typeToWeave' itself. 'typesToWeave' is then removed from the
  1179. * 'typesForWeaving' list.
  1180. *
  1181. * Note: Future gotcha in here ... when supplying partial hierarchies, this algorithm may break down. If you have a hierarchy
  1182. * A>B>C and only give A and C to the weaver, it may choose to weave them in either order - but you'll probably have other
  1183. * problems if you are supplying partial hierarchies like that !
  1184. */
  1185. private void weaveParentsFor(List<String> typesForWeaving, String typeToWeave, ResolvedType resolvedTypeToWeave) {
  1186. if (resolvedTypeToWeave == null) {
  1187. // resolve it if the caller could not pass in the resolved type
  1188. resolvedTypeToWeave = world.resolve(typeToWeave);
  1189. }
  1190. ResolvedType superclassType = resolvedTypeToWeave.getSuperclass();
  1191. String superclassTypename = (superclassType == null ? null : superclassType.getName());
  1192. // PR336654 added the 'typesForWeaving.contains(superclassTypename)' clause.
  1193. // Without it we can delete all type mungers on the parents and yet we only
  1194. // add back in the declare parents related ones, not the regular ITDs.
  1195. if (superclassType != null && !superclassType.isTypeHierarchyComplete() && superclassType.isExposedToWeaver()
  1196. && typesForWeaving.contains(superclassTypename)) {
  1197. weaveParentsFor(typesForWeaving, superclassTypename, superclassType);
  1198. }
  1199. ResolvedType[] interfaceTypes = resolvedTypeToWeave.getDeclaredInterfaces();
  1200. for (ResolvedType resolvedSuperInterface : interfaceTypes) {
  1201. if (!resolvedSuperInterface.isTypeHierarchyComplete()) {
  1202. String interfaceTypename = resolvedSuperInterface.getName();
  1203. if (resolvedSuperInterface.isExposedToWeaver()) { // typesForWeaving.contains(interfaceTypename)) {
  1204. weaveParentsFor(typesForWeaving, interfaceTypename, resolvedSuperInterface);
  1205. }
  1206. }
  1207. }
  1208. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_PARENTS,
  1209. resolvedTypeToWeave.getName());
  1210. // If A was processed before B (and was declared 'class A implements B') then there is no need to complete B again, it
  1211. // will have been done whilst processing A.
  1212. if (!resolvedTypeToWeave.isTypeHierarchyComplete()) {
  1213. weaveParentTypeMungers(resolvedTypeToWeave);
  1214. }
  1215. CompilationAndWeavingContext.leavingPhase(tok);
  1216. typesForWeaving.remove(typeToWeave);
  1217. resolvedTypeToWeave.tagAsTypeHierarchyComplete();
  1218. }
  1219. public void prepareToProcessReweavableState() {
  1220. }
  1221. public void processReweavableStateIfPresent(String className, BcelObjectType classType) {
  1222. // If the class is marked reweavable, check any aspects around when it
  1223. // was built are in this world
  1224. WeaverStateInfo wsi = classType.getWeaverState();
  1225. // System.out.println(">> processReweavableStateIfPresent " + className + " wsi=" + wsi);
  1226. if (wsi != null && wsi.isReweavable()) { // Check all necessary types
  1227. // are around!
  1228. world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.PROCESSING_REWEAVABLE, className, classType
  1229. .getSourceLocation().getSourceFile()), null, null);
  1230. Set<String> aspectsPreviouslyInWorld = wsi.getAspectsAffectingType();
  1231. // keep track of them just to ensure unique missing aspect error
  1232. // reporting
  1233. Set<String> alreadyConfirmedReweavableState = new HashSet<String>();
  1234. for (String requiredTypeSignature : aspectsPreviouslyInWorld) {
  1235. // for (Iterator iter = aspectsPreviouslyInWorld.iterator(); iter.hasNext();) {
  1236. // String requiredTypeName = (String) iter.next();
  1237. if (!alreadyConfirmedReweavableState.contains(requiredTypeSignature)) {
  1238. ResolvedType rtx = world.resolve(UnresolvedType.forSignature(requiredTypeSignature), true);
  1239. boolean exists = !rtx.isMissing();
  1240. if (!exists) {
  1241. world.getLint().missingAspectForReweaving.signal(new String[] { rtx.getName(), className },
  1242. classType.getSourceLocation(), null);
  1243. // world.showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.MISSING_REWEAVABLE_TYPE,
  1244. // requiredTypeName, className), classType.getSourceLocation(), null);
  1245. } else {
  1246. if (world.isOverWeaving()) {
  1247. // System.out.println(">> Removing " + requiredTypeName + " from weaving process: "
  1248. // + xcutSet.deleteAspect(rtx));
  1249. } else {
  1250. // weaved in aspect that are not declared in aop.xml
  1251. // trigger an error for now
  1252. // may cause headhache for LTW and packaged lib
  1253. // without aop.xml in
  1254. // see #104218
  1255. if (!xcutSet.containsAspect(rtx)) {
  1256. world.showMessage(IMessage.ERROR, WeaverMessages.format(
  1257. WeaverMessages.REWEAVABLE_ASPECT_NOT_REGISTERED, rtx.getName(), className), null, null);
  1258. } else if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
  1259. world.showMessage(IMessage.INFO, WeaverMessages.format(WeaverMessages.VERIFIED_REWEAVABLE_TYPE,
  1260. rtx.getName(), rtx.getSourceLocation().getSourceFile()), null, null);
  1261. }
  1262. }
  1263. alreadyConfirmedReweavableState.add(requiredTypeSignature);
  1264. }
  1265. }
  1266. }
  1267. // old:
  1268. // classType.setJavaClass(Utility.makeJavaClass(classType.getJavaClass
  1269. // ().getFileName(), wsi.getUnwovenClassFileData()));
  1270. // new: reweavable default with clever diff
  1271. if (!world.isOverWeaving()) {
  1272. byte[] bytes = wsi.getUnwovenClassFileData(classType.getJavaClass().getBytes());
  1273. WeaverVersionInfo wvi = classType.getWeaverVersionAttribute();
  1274. JavaClass newJavaClass = Utility.makeJavaClass(classType.getJavaClass().getFileName(), bytes);
  1275. classType.setJavaClass(newJavaClass, true);
  1276. classType.getResolvedTypeX().ensureConsistent();
  1277. }
  1278. // } else {
  1279. // classType.resetState();
  1280. }
  1281. }
  1282. private void weaveAndNotify(UnwovenClassFile classFile, BcelObjectType classType, IWeaveRequestor requestor) throws IOException {
  1283. trace.enter("weaveAndNotify", this, new Object[] { classFile, classType, requestor });
  1284. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_TYPE, classType
  1285. .getResolvedTypeX().getName());
  1286. LazyClassGen clazz = weaveWithoutDump(classFile, classType);
  1287. classType.finishedWith();
  1288. // clazz is null if the classfile was unchanged by weaving...
  1289. if (clazz != null) {
  1290. UnwovenClassFile[] newClasses = getClassFilesFor(clazz);
  1291. // OPTIMIZE can we avoid using the string name at all in
  1292. // UnwovenClassFile instances?
  1293. // Copy the char[] across as it means the
  1294. // WeaverAdapter.removeFromMap() can be fast!
  1295. if (newClasses[0].getClassName().equals(classFile.getClassName())) {
  1296. newClasses[0].setClassNameAsChars(classFile.getClassNameAsChars());
  1297. }
  1298. for (int i = 0; i < newClasses.length; i++) {
  1299. requestor.acceptResult(newClasses[i]);
  1300. }
  1301. } else {
  1302. requestor.acceptResult(classFile);
  1303. }
  1304. classType.weavingCompleted();
  1305. CompilationAndWeavingContext.leavingPhase(tok);
  1306. trace.exit("weaveAndNotify");
  1307. }
  1308. /**
  1309. * helper method - will return NULL if the underlying delegate is an EclipseSourceType and not a BcelObjectType
  1310. */
  1311. public BcelObjectType getClassType(String forClass) {
  1312. return BcelWorld.getBcelObjectType(world.resolve(forClass));
  1313. }
  1314. public void addParentTypeMungers(String typeName) {
  1315. weaveParentTypeMungers(world.resolve(typeName));
  1316. }
  1317. public void addNormalTypeMungers(String typeName) {
  1318. weaveNormalTypeMungers(world.resolve(typeName));
  1319. }
  1320. public UnwovenClassFile[] getClassFilesFor(LazyClassGen clazz) {
  1321. List<UnwovenClassFile.ChildClass> childClasses = clazz.getChildClasses(world);
  1322. UnwovenClassFile[] ret = new UnwovenClassFile[1 + childClasses.size()];
  1323. ret[0] = new UnwovenClassFile(clazz.getFileName(), clazz.getClassName(), clazz.getJavaClassBytesIncludingReweavable(world));
  1324. int index = 1;
  1325. for (Iterator<UnwovenClassFile.ChildClass> iter = childClasses.iterator(); iter.hasNext();) {
  1326. UnwovenClassFile.ChildClass element = iter.next();
  1327. UnwovenClassFile childClass = new UnwovenClassFile(clazz.getFileName() + "$" + element.name, element.bytes);
  1328. ret[index++] = childClass;
  1329. }
  1330. return ret;
  1331. }
  1332. /**
  1333. * Weaves new parents and annotations onto a type ("declare parents" and "declare @type")
  1334. *
  1335. * Algorithm: 1. First pass, do parents then do annotations. During this pass record: - any parent mungers that don't match but
  1336. * have a non-wild annotation type pattern - any annotation mungers that don't match 2. Multiple subsequent passes which go over
  1337. * the munger lists constructed in the first pass, repeatedly applying them until nothing changes. FIXME asc confirm that
  1338. * algorithm is optimal ??
  1339. */
  1340. public void weaveParentTypeMungers(ResolvedType onType) {
  1341. if (onType.isRawType() || onType.isParameterizedType()) {
  1342. onType = onType.getGenericType();
  1343. }
  1344. onType.clearInterTypeMungers();
  1345. List<DeclareParents> decpToRepeat = new ArrayList<DeclareParents>();
  1346. boolean aParentChangeOccurred = false;
  1347. boolean anAnnotationChangeOccurred = false;
  1348. // First pass - apply all decp mungers
  1349. for (DeclareParents decp : declareParentsList) {
  1350. boolean typeChanged = applyDeclareParents(decp, onType);
  1351. if (typeChanged) {
  1352. aParentChangeOccurred = true;
  1353. } else {
  1354. decpToRepeat.add(decp);
  1355. }
  1356. }
  1357. // Still first pass - apply all dec @type mungers
  1358. for (DeclareAnnotation decA : xcutSet.getDeclareAnnotationOnTypes()) {
  1359. boolean typeChanged = applyDeclareAtType(decA, onType, true);
  1360. if (typeChanged) {
  1361. anAnnotationChangeOccurred = true;
  1362. }
  1363. }
  1364. while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) {
  1365. anAnnotationChangeOccurred = aParentChangeOccurred = false;
  1366. List<DeclareParents> decpToRepeatNextTime = new ArrayList<DeclareParents>();
  1367. for (Iterator<DeclareParents> iter = decpToRepeat.iterator(); iter.hasNext();) {
  1368. DeclareParents decp = iter.next();
  1369. boolean typeChanged = applyDeclareParents(decp, onType);
  1370. if (typeChanged) {
  1371. aParentChangeOccurred = true;
  1372. } else {
  1373. decpToRepeatNextTime.add(decp);
  1374. }
  1375. }
  1376. for (DeclareAnnotation decA : xcutSet.getDeclareAnnotationOnTypes()) {
  1377. boolean typeChanged = applyDeclareAtType(decA, onType, false);
  1378. if (typeChanged) {
  1379. anAnnotationChangeOccurred = true;
  1380. }
  1381. }
  1382. decpToRepeat = decpToRepeatNextTime;
  1383. }
  1384. }
  1385. /**
  1386. * Apply a declare @type - return true if we change the type
  1387. */
  1388. private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType, boolean reportProblems) {
  1389. boolean didSomething = false;
  1390. if (decA.matches(onType)) {
  1391. AnnotationAJ theAnnotation = decA.getAnnotation();
  1392. // can be null for broken code!
  1393. if (theAnnotation == null) {
  1394. return false;
  1395. }
  1396. if (onType.hasAnnotation(theAnnotation.getType())) {
  1397. // Could put out a lint here for an already annotated type ...
  1398. // if (reportProblems) {
  1399. // world.getLint().elementAlreadyAnnotated.signal(
  1400. // new
  1401. // String[]{onType.toString(),decA.getAnnotationTypeX().toString
  1402. // ()},
  1403. // onType.getSourceLocation(),new
  1404. // ISourceLocation[]{decA.getSourceLocation()});
  1405. // }
  1406. return false;
  1407. }
  1408. AnnotationAJ annoX = decA.getAnnotation();
  1409. // check the annotation is suitable for the target
  1410. boolean problemReported = verifyTargetIsOK(decA, onType, annoX, reportProblems);
  1411. if (!problemReported) {
  1412. AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(), decA.getSourceLocation(),
  1413. onType.getSourceLocation(), false);
  1414. // TAG: WeavingMessage
  1415. if (!getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
  1416. getWorld().getMessageHandler().handleMessage(
  1417. WeaveMessage.constructWeavingMessage(
  1418. WeaveMessage.WEAVEMESSAGE_ANNOTATES,
  1419. new String[] { onType.toString(), Utility.beautifyLocation(onType.getSourceLocation()),
  1420. decA.getAnnotationString(), "type", decA.getAspect().toString(),
  1421. Utility.beautifyLocation(decA.getSourceLocation()) }));
  1422. }
  1423. didSomething = true;
  1424. ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX);
  1425. newAnnotationTM.setSourceLocation(decA.getSourceLocation());
  1426. onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, decA.getAspect().resolve(world)), false);
  1427. decA.copyAnnotationTo(onType);
  1428. }
  1429. }
  1430. return didSomething;
  1431. }
  1432. /**
  1433. * Checks for an @target() on the annotation and if found ensures it allows the annotation to be attached to the target type
  1434. * that matched.
  1435. */
  1436. private boolean verifyTargetIsOK(DeclareAnnotation decA, ResolvedType onType, AnnotationAJ annoX, boolean outputProblems) {
  1437. boolean problemReported = false;
  1438. if (annoX.specifiesTarget()) {
  1439. if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || (!annoX.allowedOnRegularType())) {
  1440. if (outputProblems) {
  1441. if (decA.isExactPattern()) {
  1442. world.getMessageHandler().handleMessage(
  1443. MessageUtil.error(
  1444. WeaverMessages.format(WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION,
  1445. onType.getName(), annoX.getTypeName(), annoX.getValidTargets()),
  1446. decA.getSourceLocation()));
  1447. } else {
  1448. if (world.getLint().invalidTargetForAnnotation.isEnabled()) {
  1449. world.getLint().invalidTargetForAnnotation.signal(new String[] { onType.getName(), annoX.getTypeName(),
  1450. annoX.getValidTargets() }, decA.getSourceLocation(),
  1451. new ISourceLocation[] { onType.getSourceLocation() });
  1452. }
  1453. }
  1454. }
  1455. problemReported = true;
  1456. }
  1457. }
  1458. return problemReported;
  1459. }
  1460. /**
  1461. * Apply a single declare parents - return true if we change the type
  1462. */
  1463. private boolean applyDeclareParents(DeclareParents p, ResolvedType onType) {
  1464. boolean didSomething = false;
  1465. List<ResolvedType> newParents = p.findMatchingNewParents(onType, true);
  1466. if (!newParents.isEmpty()) {
  1467. didSomething = true;
  1468. BcelWorld.getBcelObjectType(onType);
  1469. // System.err.println("need to do declare parents for: " + onType);
  1470. for (ResolvedType newParent : newParents) {
  1471. // We set it here so that the imminent matching for ITDs can
  1472. // succeed - we still haven't done the necessary changes to the class file
  1473. // itself (like transform super calls) - that is done in
  1474. // BcelTypeMunger.mungeNewParent()
  1475. // classType.addParent(newParent);
  1476. onType.addParent(newParent);
  1477. NewParentTypeMunger newParentMunger = new NewParentTypeMunger(newParent, p.getDeclaringType());
  1478. if (p.isMixin()) {
  1479. newParentMunger.setIsMixin(true);
  1480. }
  1481. newParentMunger.setSourceLocation(p.getSourceLocation());
  1482. onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, xcutSet.findAspectDeclaringParents(p)), false);
  1483. }
  1484. }
  1485. return didSomething;
  1486. }
  1487. public void weaveNormalTypeMungers(ResolvedType onType) {
  1488. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_TYPE_MUNGERS,
  1489. onType.getName());
  1490. if (onType.isRawType() || onType.isParameterizedType()) {
  1491. onType = onType.getGenericType();
  1492. }
  1493. for (ConcreteTypeMunger m : typeMungerList) {
  1494. if (!m.isLateMunger() && m.matches(onType)) {
  1495. onType.addInterTypeMunger(m, false);
  1496. }
  1497. }
  1498. CompilationAndWeavingContext.leavingPhase(tok);
  1499. }
  1500. // exposed for ClassLoader dynamic weaving
  1501. public LazyClassGen weaveWithoutDump(UnwovenClassFile classFile, BcelObjectType classType) throws IOException {
  1502. return weave(classFile, classType, false);
  1503. }
  1504. // FOR TESTING
  1505. LazyClassGen weave(UnwovenClassFile classFile, BcelObjectType classType) throws IOException {
  1506. LazyClassGen ret = weave(classFile, classType, true);
  1507. return ret;
  1508. }
  1509. private LazyClassGen weave(UnwovenClassFile classFile, BcelObjectType classType, boolean dump) throws IOException {
  1510. try {
  1511. if (classType.isSynthetic()) { // Don't touch synthetic classes
  1512. if (dump) {
  1513. dumpUnchanged(classFile);
  1514. }
  1515. return null;
  1516. }
  1517. ReferenceType resolvedClassType = classType.getResolvedTypeX();
  1518. if (world.isXmlConfigured() && world.getXmlConfiguration().excludesType(resolvedClassType)) {
  1519. if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
  1520. world.getMessageHandler().handleMessage(
  1521. MessageUtil.info("Type '" + resolvedClassType.getName()
  1522. + "' not woven due to exclusion via XML weaver exclude section"));
  1523. }
  1524. if (dump) {
  1525. dumpUnchanged(classFile);
  1526. }
  1527. return null;
  1528. }
  1529. List<ShadowMunger> shadowMungers = fastMatch(shadowMungerList, resolvedClassType);
  1530. List<ConcreteTypeMunger> typeMungers = classType.getResolvedTypeX().getInterTypeMungers();
  1531. resolvedClassType.checkInterTypeMungers();
  1532. // Decide if we need to do actual weaving for this class
  1533. boolean mightNeedToWeave = shadowMungers.size() > 0 || typeMungers.size() > 0 || classType.isAspect()
  1534. || world.getDeclareAnnotationOnMethods().size() > 0 || world.getDeclareAnnotationOnFields().size() > 0;
  1535. // May need bridge methods if on 1.5 and something in our hierarchy is
  1536. // affected by ITDs
  1537. boolean mightNeedBridgeMethods = world.isInJava5Mode() && !classType.isInterface()
  1538. && resolvedClassType.getInterTypeMungersIncludingSupers().size() > 0;
  1539. LazyClassGen clazz = null;
  1540. if (mightNeedToWeave || mightNeedBridgeMethods) {
  1541. clazz = classType.getLazyClassGen();
  1542. // System.err.println("got lazy gen: " + clazz + ", " +
  1543. // clazz.getWeaverState());
  1544. try {
  1545. boolean isChanged = false;
  1546. if (mightNeedToWeave) {
  1547. isChanged = BcelClassWeaver.weave(world, clazz, shadowMungers, typeMungers, lateTypeMungerList,
  1548. inReweavableMode);
  1549. }
  1550. checkDeclareTypeErrorOrWarning(world, classType);
  1551. if (mightNeedBridgeMethods) {
  1552. isChanged = BcelClassWeaver.calculateAnyRequiredBridgeMethods(world, clazz) || isChanged;
  1553. }
  1554. if (isChanged) {
  1555. if (dump) {
  1556. dump(classFile, clazz);
  1557. }
  1558. return clazz;
  1559. }
  1560. } catch (RuntimeException re) {
  1561. String classDebugInfo = null;
  1562. try {
  1563. classDebugInfo = clazz.toLongString();
  1564. } catch (Throwable e) {
  1565. new RuntimeException("Crashed whilst crashing with this exception: " + e, e).printStackTrace();
  1566. // recover from crash whilst producing debug string
  1567. classDebugInfo = clazz.getClassName();
  1568. }
  1569. String messageText = "trouble in: \n" + classDebugInfo;
  1570. getWorld().getMessageHandler().handleMessage(new Message(messageText, IMessage.ABORT, re, null));
  1571. } catch (Error re) {
  1572. String classDebugInfo = null;
  1573. try {
  1574. classDebugInfo = clazz.toLongString();
  1575. } catch (OutOfMemoryError oome) {
  1576. System.err.println("Ran out of memory creating debug info for an error");
  1577. re.printStackTrace(System.err);
  1578. // recover from crash whilst producing debug string
  1579. classDebugInfo = clazz.getClassName();
  1580. } catch (Throwable e) {
  1581. // recover from crash whilst producing debug string
  1582. classDebugInfo = clazz.getClassName();
  1583. }
  1584. String messageText = "trouble in: \n" + classDebugInfo;
  1585. getWorld().getMessageHandler().handleMessage(new Message(messageText, IMessage.ABORT, re, null));
  1586. }
  1587. } else {
  1588. checkDeclareTypeErrorOrWarning(world, classType);
  1589. }
  1590. // this is very odd return behavior trying to keep everyone happy
  1591. // can we remove it from the model now? we know it contains no relationship endpoints...
  1592. AsmManager model = world.getModelAsAsmManager();
  1593. if (world.isMinimalModel() && model != null && !classType.isAspect()) {
  1594. AspectJElementHierarchy hierarchy = (AspectJElementHierarchy) model.getHierarchy();
  1595. String pkgname = classType.getResolvedTypeX().getPackageName();
  1596. String tname = classType.getResolvedTypeX().getSimpleBaseName();
  1597. IProgramElement typeElement = hierarchy.findElementForType(pkgname, tname);
  1598. if (typeElement != null && hasInnerType(typeElement)) {
  1599. // Cannot remove it right now (has inner type), schedule it
  1600. // for possible deletion later if all inner types are
  1601. // removed
  1602. candidatesForRemoval.add(typeElement);
  1603. }
  1604. if (typeElement != null && !hasInnerType(typeElement)) {
  1605. IProgramElement parent = typeElement.getParent();
  1606. // parent may have children: PACKAGE DECL, IMPORT-REFERENCE, TYPE_DECL
  1607. if (parent != null) {
  1608. // if it was the only type we should probably remove
  1609. // the others too.
  1610. parent.removeChild(typeElement);
  1611. if (parent.getKind().isSourceFile()) {
  1612. removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeElement, parent);
  1613. } else {
  1614. hierarchy.forget(null, typeElement);
  1615. // At this point, the child has been removed. We
  1616. // should now check if the parent is in our
  1617. // 'candidatesForRemoval' set. If it is then that
  1618. // means we were going to remove it but it had a
  1619. // child. Now we can check if it still has a child -
  1620. // if it doesn't it can also be removed!
  1621. walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent);
  1622. }
  1623. }
  1624. }
  1625. }
  1626. if (dump) {
  1627. dumpUnchanged(classFile);
  1628. return clazz;
  1629. } else {
  1630. // ATAJ: the class was not weaved, but since it gets there early it
  1631. // may have new generated inner classes
  1632. // attached to it to support LTW perX aspectOf support (see
  1633. // BcelPerClauseAspectAdder)
  1634. // that aggressively defines the inner <aspect>$mayHaveAspect
  1635. // interface.
  1636. if (clazz != null && !clazz.getChildClasses(world).isEmpty()) {
  1637. return clazz;
  1638. }
  1639. return null;
  1640. }
  1641. } finally {
  1642. world.demote();
  1643. }
  1644. }
  1645. private void walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(AspectJElementHierarchy hierarchy, String tname,
  1646. IProgramElement typeThatHasChildRemoved) {
  1647. // typeThatHasChildRemoved might be a source file, type or a method/ctor
  1648. // - for a method/ctor find the type/sourcefile
  1649. while (typeThatHasChildRemoved != null
  1650. && !(typeThatHasChildRemoved.getKind().isType() || typeThatHasChildRemoved.getKind().isSourceFile())) {
  1651. // this will take us 'up' through methods that contain anonymous
  1652. // inner classes
  1653. typeThatHasChildRemoved = typeThatHasChildRemoved.getParent();
  1654. }
  1655. // now typeThatHasChildRemoved points to the type or sourcefile that has
  1656. // had something removed
  1657. if (candidatesForRemoval.contains(typeThatHasChildRemoved) && !hasInnerType(typeThatHasChildRemoved)) {
  1658. // now we can get rid of it
  1659. IProgramElement parent = typeThatHasChildRemoved.getParent();
  1660. if (parent != null) {
  1661. parent.removeChild(typeThatHasChildRemoved);
  1662. candidatesForRemoval.remove(typeThatHasChildRemoved);
  1663. if (parent.getKind().isSourceFile()) {
  1664. removeSourceFileIfNoMoreTypeDeclarationsInside(hierarchy, typeThatHasChildRemoved, parent);
  1665. // System.out.println("Removed on second pass: " +
  1666. // typeThatHasChildRemoved.getName());
  1667. } else {
  1668. // System.out.println("On later pass, parent of type " +
  1669. // typeThatHasChildRemoved.getName()
  1670. // + " was found not to be a sourcefile, recursing up...");
  1671. walkUpRemovingEmptyTypesAndPossiblyEmptySourceFile(hierarchy, tname, parent);
  1672. }
  1673. }
  1674. }
  1675. }
  1676. private void removeSourceFileIfNoMoreTypeDeclarationsInside(AspectJElementHierarchy hierarchy, IProgramElement typeElement,
  1677. IProgramElement sourceFileNode) {
  1678. IProgramElement compilationUnit = sourceFileNode;
  1679. boolean anyOtherTypeDeclarations = false;
  1680. for (IProgramElement child : compilationUnit.getChildren()) {
  1681. IProgramElement.Kind k = child.getKind();
  1682. if (k.isType()) {
  1683. anyOtherTypeDeclarations = true;
  1684. break;
  1685. }
  1686. }
  1687. // If the compilation unit node contained no
  1688. // other types, there is no need to keep it
  1689. if (!anyOtherTypeDeclarations) {
  1690. IProgramElement cuParent = compilationUnit.getParent();
  1691. if (cuParent != null) {
  1692. compilationUnit.setParent(null);
  1693. cuParent.removeChild(compilationUnit);
  1694. }
  1695. // need to update some caches and structures too?
  1696. hierarchy.forget(sourceFileNode, typeElement);
  1697. } else {
  1698. hierarchy.forget(null, typeElement);
  1699. }
  1700. }
  1701. // ---- writing
  1702. // TODO could be smarter - really only matters if inner type has been woven, but there is a chance we haven't woven it *yet*
  1703. private boolean hasInnerType(IProgramElement typeNode) {
  1704. for (IProgramElement child : typeNode.getChildren()) {
  1705. IProgramElement.Kind kind = child.getKind();
  1706. if (kind.isType()) {
  1707. return true;
  1708. }
  1709. // if (kind == IProgramElement.Kind.ASPECT) {
  1710. // return true;
  1711. // }
  1712. if (kind.isType() || kind == IProgramElement.Kind.METHOD || kind == IProgramElement.Kind.CONSTRUCTOR) {
  1713. boolean b = hasInnerType(child);
  1714. if (b) {
  1715. return b;
  1716. }
  1717. }
  1718. }
  1719. return false;
  1720. }
  1721. private void checkDeclareTypeErrorOrWarning(BcelWorld world2, BcelObjectType classType) {
  1722. List<DeclareTypeErrorOrWarning> dteows = world.getDeclareTypeEows();
  1723. for (DeclareTypeErrorOrWarning dteow : dteows) {
  1724. if (dteow.getTypePattern().matchesStatically(classType.getResolvedTypeX())) {
  1725. if (dteow.isError()) {
  1726. world.getMessageHandler().handleMessage(
  1727. MessageUtil.error(dteow.getMessage(), classType.getResolvedTypeX().getSourceLocation()));
  1728. } else {
  1729. world.getMessageHandler().handleMessage(
  1730. MessageUtil.warn(dteow.getMessage(), classType.getResolvedTypeX().getSourceLocation()));
  1731. }
  1732. }
  1733. }
  1734. }
  1735. private void dumpUnchanged(UnwovenClassFile classFile) throws IOException {
  1736. if (zipOutputStream != null) {
  1737. writeZipEntry(getEntryName(classFile.getJavaClass().getClassName()), classFile.getBytes());
  1738. } else {
  1739. classFile.writeUnchangedBytes();
  1740. }
  1741. }
  1742. private String getEntryName(String className) {
  1743. // XXX what does bcel's getClassName do for inner names
  1744. return className.replace('.', '/') + ".class";
  1745. }
  1746. private void dump(UnwovenClassFile classFile, LazyClassGen clazz) throws IOException {
  1747. if (zipOutputStream != null) {
  1748. String mainClassName = classFile.getJavaClass().getClassName();
  1749. writeZipEntry(getEntryName(mainClassName), clazz.getJavaClass(world).getBytes());
  1750. List<UnwovenClassFile.ChildClass> childClasses = clazz.getChildClasses(world);
  1751. if (!childClasses.isEmpty()) {
  1752. for (Iterator<UnwovenClassFile.ChildClass> i = childClasses.iterator(); i.hasNext();) {
  1753. UnwovenClassFile.ChildClass c = i.next();
  1754. writeZipEntry(getEntryName(mainClassName + "$" + c.name), c.bytes);
  1755. }
  1756. }
  1757. } else {
  1758. classFile.writeWovenBytes(clazz.getJavaClass(world).getBytes(), clazz.getChildClasses(world));
  1759. }
  1760. }
  1761. private void writeZipEntry(String name, byte[] bytes) throws IOException {
  1762. ZipEntry newEntry = new ZipEntry(name); // ??? get compression scheme
  1763. // right
  1764. zipOutputStream.putNextEntry(newEntry);
  1765. zipOutputStream.write(bytes);
  1766. zipOutputStream.closeEntry();
  1767. }
  1768. /**
  1769. * Perform a fast match of the specified list of shadowmungers against the specified type. A subset of those that might match is
  1770. * returned.
  1771. *
  1772. * @param list list of all shadow mungers that might match
  1773. * @param type the target type
  1774. * @return a list of shadow mungers that might match with those that cannot (according to fast match rules) removed
  1775. */
  1776. private List<ShadowMunger> fastMatch(List<ShadowMunger> list, ResolvedType type) {
  1777. if (list == null) {
  1778. return Collections.emptyList();
  1779. }
  1780. boolean isOverweaving = world.isOverWeaving();
  1781. WeaverStateInfo typeWeaverState = (isOverweaving ? type.getWeaverState() : null);
  1782. // here we do the coarsest grained fast match with no kind constraints
  1783. // this will remove all obvious non-matches and see if we need to do any
  1784. // weaving
  1785. FastMatchInfo info = new FastMatchInfo(type, null, world);
  1786. List<ShadowMunger> result = new ArrayList<ShadowMunger>();
  1787. if (world.areInfoMessagesEnabled() && world.isTimingEnabled()) {
  1788. for (ShadowMunger munger : list) {
  1789. if (typeWeaverState != null) { // will only be null if overweaving is ON and there is weaverstate
  1790. ResolvedType declaringAspect = munger.getDeclaringType();
  1791. if (typeWeaverState.isAspectAlreadyApplied(declaringAspect)) {
  1792. continue;
  1793. }
  1794. }
  1795. Pointcut pointcut = munger.getPointcut();
  1796. long starttime = System.nanoTime();
  1797. FuzzyBoolean fb = pointcut.fastMatch(info);
  1798. long endtime = System.nanoTime();
  1799. world.recordFastMatch(pointcut, endtime - starttime);
  1800. if (fb.maybeTrue()) {
  1801. result.add(munger);
  1802. }
  1803. }
  1804. } else {
  1805. for (ShadowMunger munger : list) {
  1806. if (typeWeaverState != null) { // will only be null if overweaving is ON and there is weaverstate
  1807. ResolvedType declaringAspect = munger.getConcreteAspect();// getDeclaringType();
  1808. if (typeWeaverState.isAspectAlreadyApplied(declaringAspect)) {
  1809. continue;
  1810. }
  1811. }
  1812. Pointcut pointcut = munger.getPointcut();
  1813. FuzzyBoolean fb = pointcut.fastMatch(info);
  1814. if (fb.maybeTrue()) {
  1815. result.add(munger);
  1816. }
  1817. }
  1818. }
  1819. return result;
  1820. }
  1821. public void setReweavableMode(boolean xNotReweavable) {
  1822. inReweavableMode = !xNotReweavable;
  1823. WeaverStateInfo.setReweavableModeDefaults(!xNotReweavable, false, true);
  1824. }
  1825. public boolean isReweavable() {
  1826. return inReweavableMode;
  1827. }
  1828. public World getWorld() {
  1829. return world;
  1830. }
  1831. public void tidyUp() {
  1832. if (trace.isTraceEnabled()) {
  1833. trace.enter("tidyUp", this);
  1834. }
  1835. shadowMungerList = null; // setup by prepareForWeave
  1836. typeMungerList = null; // setup by prepareForWeave
  1837. lateTypeMungerList = null; // setup by prepareForWeave
  1838. declareParentsList = null; // setup by prepareForWeave
  1839. if (trace.isTraceEnabled()) {
  1840. trace.exit("tidyUp");
  1841. }
  1842. }
  1843. public void write(CompressingDataOutputStream dos) throws IOException {
  1844. xcutSet.write(dos);
  1845. }
  1846. // only called for testing
  1847. public void setShadowMungers(List<ShadowMunger> shadowMungers) {
  1848. shadowMungerList = shadowMungers;
  1849. }
  1850. }