Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

BcelWorld.java 48KB

vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 15 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 21 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 15 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 21 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 21 Jahren
vor 21 Jahren
vor 21 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 12 Jahren
vor 14 Jahren
vor 14 Jahren
vor 12 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 12 Jahren
vor 12 Jahren
vor 12 Jahren
vor 12 Jahren
vor 14 Jahren
vor 14 Jahren
vor 15 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 11 Jahren
vor 11 Jahren
vor 11 Jahren
vor 11 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
vor 14 Jahren
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Alexandre Vasseur perClause support for @AJ aspects
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.io.File;
  15. import java.io.IOException;
  16. import java.lang.reflect.Modifier;
  17. import java.net.MalformedURLException;
  18. import java.util.ArrayList;
  19. import java.util.Collections;
  20. import java.util.HashMap;
  21. import java.util.Iterator;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.StringTokenizer;
  25. import org.aspectj.apache.bcel.Constants;
  26. import org.aspectj.apache.bcel.classfile.ClassParser;
  27. import org.aspectj.apache.bcel.classfile.ConstantPool;
  28. import org.aspectj.apache.bcel.classfile.JavaClass;
  29. import org.aspectj.apache.bcel.generic.FieldInstruction;
  30. import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
  31. import org.aspectj.apache.bcel.generic.Instruction;
  32. import org.aspectj.apache.bcel.generic.InstructionHandle;
  33. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  34. import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
  35. import org.aspectj.apache.bcel.generic.ObjectType;
  36. import org.aspectj.apache.bcel.generic.Type;
  37. import org.aspectj.apache.bcel.util.ClassLoaderReference;
  38. import org.aspectj.apache.bcel.util.ClassLoaderRepository;
  39. import org.aspectj.apache.bcel.util.ClassPath;
  40. import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository;
  41. import org.aspectj.apache.bcel.util.Repository;
  42. import org.aspectj.asm.AsmManager;
  43. import org.aspectj.asm.IRelationship;
  44. import org.aspectj.asm.internal.CharOperation;
  45. import org.aspectj.bridge.IMessage;
  46. import org.aspectj.bridge.IMessageHandler;
  47. import org.aspectj.bridge.ISourceLocation;
  48. import org.aspectj.bridge.Message;
  49. import org.aspectj.bridge.MessageUtil;
  50. import org.aspectj.bridge.WeaveMessage;
  51. import org.aspectj.weaver.Advice;
  52. import org.aspectj.weaver.AdviceKind;
  53. import org.aspectj.weaver.AnnotationAJ;
  54. import org.aspectj.weaver.AnnotationOnTypeMunger;
  55. import org.aspectj.weaver.BCException;
  56. import org.aspectj.weaver.Checker;
  57. import org.aspectj.weaver.ICrossReferenceHandler;
  58. import org.aspectj.weaver.IWeavingSupport;
  59. import org.aspectj.weaver.Member;
  60. import org.aspectj.weaver.MemberImpl;
  61. import org.aspectj.weaver.MemberKind;
  62. import org.aspectj.weaver.NewParentTypeMunger;
  63. import org.aspectj.weaver.ReferenceType;
  64. import org.aspectj.weaver.ReferenceTypeDelegate;
  65. import org.aspectj.weaver.ResolvedMember;
  66. import org.aspectj.weaver.ResolvedMemberImpl;
  67. import org.aspectj.weaver.ResolvedType;
  68. import org.aspectj.weaver.ResolvedTypeMunger;
  69. import org.aspectj.weaver.Shadow;
  70. import org.aspectj.weaver.ShadowMunger;
  71. import org.aspectj.weaver.UnresolvedType;
  72. import org.aspectj.weaver.World;
  73. import org.aspectj.weaver.loadtime.definition.Definition;
  74. import org.aspectj.weaver.loadtime.definition.DocumentParser;
  75. import org.aspectj.weaver.model.AsmRelationshipProvider;
  76. import org.aspectj.weaver.patterns.DeclareAnnotation;
  77. import org.aspectj.weaver.patterns.DeclareParents;
  78. import org.aspectj.weaver.patterns.ParserException;
  79. import org.aspectj.weaver.patterns.PatternParser;
  80. import org.aspectj.weaver.patterns.TypePattern;
  81. import org.aspectj.weaver.tools.Trace;
  82. import org.aspectj.weaver.tools.TraceFactory;
  83. public class BcelWorld extends World implements Repository {
  84. private final ClassPathManager classPath;
  85. protected Repository delegate;
  86. private BcelWeakClassLoaderReference loaderRef;
  87. private final BcelWeavingSupport bcelWeavingSupport = new BcelWeavingSupport();
  88. private boolean isXmlConfiguredWorld = false;
  89. private WeavingXmlConfig xmlConfiguration;
  90. private List<TypeDelegateResolver> typeDelegateResolvers;
  91. private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelWorld.class);
  92. public BcelWorld() {
  93. this("");
  94. }
  95. public BcelWorld(String cp) {
  96. this(makeDefaultClasspath(cp), IMessageHandler.THROW, null);
  97. }
  98. public IRelationship.Kind determineRelKind(ShadowMunger munger) {
  99. AdviceKind ak = ((Advice) munger).getKind();
  100. if (ak.getKey() == AdviceKind.Before.getKey()) {
  101. return IRelationship.Kind.ADVICE_BEFORE;
  102. } else if (ak.getKey() == AdviceKind.After.getKey()) {
  103. return IRelationship.Kind.ADVICE_AFTER;
  104. } else if (ak.getKey() == AdviceKind.AfterThrowing.getKey()) {
  105. return IRelationship.Kind.ADVICE_AFTERTHROWING;
  106. } else if (ak.getKey() == AdviceKind.AfterReturning.getKey()) {
  107. return IRelationship.Kind.ADVICE_AFTERRETURNING;
  108. } else if (ak.getKey() == AdviceKind.Around.getKey()) {
  109. return IRelationship.Kind.ADVICE_AROUND;
  110. } else if (ak.getKey() == AdviceKind.CflowEntry.getKey() || ak.getKey() == AdviceKind.CflowBelowEntry.getKey()
  111. || ak.getKey() == AdviceKind.InterInitializer.getKey() || ak.getKey() == AdviceKind.PerCflowEntry.getKey()
  112. || ak.getKey() == AdviceKind.PerCflowBelowEntry.getKey() || ak.getKey() == AdviceKind.PerThisEntry.getKey()
  113. || ak.getKey() == AdviceKind.PerTargetEntry.getKey() || ak.getKey() == AdviceKind.Softener.getKey()
  114. || ak.getKey() == AdviceKind.PerTypeWithinEntry.getKey()) {
  115. // System.err.println("Dont want a message about this: "+ak);
  116. return null;
  117. }
  118. throw new RuntimeException("Shadow.determineRelKind: What the hell is it? " + ak);
  119. }
  120. @Override
  121. public void reportMatch(ShadowMunger munger, Shadow shadow) {
  122. if (getCrossReferenceHandler() != null) {
  123. final IRelationship.Kind kind = determineRelKind(munger);
  124. getCrossReferenceHandler().addCrossReference(
  125. munger.getSourceLocation(), // What is being applied?
  126. shadow.getSourceLocation(), // Where is it being applied?
  127. kind == null ? null : kind.getName(), // What kind of advice?
  128. ((Advice) munger).hasDynamicTests() // Is a runtime test being stuffed in the code?
  129. );
  130. }
  131. if (!getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
  132. reportWeavingMessage(munger, shadow);
  133. }
  134. if (getModel() != null) {
  135. AsmRelationshipProvider.addAdvisedRelationship(getModelAsAsmManager(), shadow, munger);
  136. }
  137. }
  138. /*
  139. * Report a message about the advice weave that has occurred. Some messing about to make it pretty ! This code is just asking
  140. * for an NPE to occur ...
  141. */
  142. private void reportWeavingMessage(ShadowMunger munger, Shadow shadow) {
  143. Advice advice = (Advice) munger;
  144. AdviceKind aKind = advice.getKind();
  145. // Only report on interesting advice kinds ...
  146. if (aKind == null || advice.getConcreteAspect() == null) {
  147. // We suspect someone is programmatically driving the weaver
  148. // (e.g. IdWeaveTestCase in the weaver testcases)
  149. return;
  150. }
  151. if (!(aKind.equals(AdviceKind.Before) || aKind.equals(AdviceKind.After) || aKind.equals(AdviceKind.AfterReturning)
  152. || aKind.equals(AdviceKind.AfterThrowing) || aKind.equals(AdviceKind.Around) || aKind.equals(AdviceKind.Softener))) {
  153. return;
  154. }
  155. // synchronized blocks are implemented with multiple monitor_exit instructions in the bytecode
  156. // (one for normal exit from the method, one for abnormal exit), we only want to tell the user
  157. // once we have advised the end of the sync block, even though under the covers we will have
  158. // woven both exit points
  159. if (shadow.getKind() == Shadow.SynchronizationUnlock) {
  160. if (advice.lastReportedMonitorExitJoinpointLocation == null) {
  161. // this is the first time through, let's continue...
  162. advice.lastReportedMonitorExitJoinpointLocation = shadow.getSourceLocation();
  163. } else {
  164. if (areTheSame(shadow.getSourceLocation(), advice.lastReportedMonitorExitJoinpointLocation)) {
  165. // Don't report it again!
  166. advice.lastReportedMonitorExitJoinpointLocation = null;
  167. return;
  168. }
  169. // hmmm, this means some kind of nesting is going on, urgh
  170. advice.lastReportedMonitorExitJoinpointLocation = shadow.getSourceLocation();
  171. }
  172. }
  173. String description = advice.getKind().toString();
  174. String advisedType = shadow.getEnclosingType().getName();
  175. String advisingType = advice.getConcreteAspect().getName();
  176. Message msg = null;
  177. if (advice.getKind().equals(AdviceKind.Softener)) {
  178. msg = WeaveMessage.constructWeavingMessage(
  179. WeaveMessage.WEAVEMESSAGE_SOFTENS,
  180. new String[] {
  181. advisedType, beautifyLocation(shadow.getSourceLocation()),
  182. advisingType, beautifyLocation(munger.getSourceLocation())
  183. },
  184. advisedType, advisingType,
  185. shadow.getSourceLocation(), munger.getSourceLocation()
  186. );
  187. }
  188. else {
  189. boolean runtimeTest = advice.hasDynamicTests();
  190. String joinPointDescription = shadow.toString();
  191. msg = WeaveMessage.constructWeavingMessage(
  192. WeaveMessage.WEAVEMESSAGE_ADVISES,
  193. new String[] {
  194. joinPointDescription,
  195. advisedType, beautifyLocation(shadow.getSourceLocation()),
  196. description,
  197. advisingType, beautifyLocation(munger.getSourceLocation()),
  198. (runtimeTest ? " [with runtime test]" : "")
  199. },
  200. advisedType, advisingType,
  201. shadow.getSourceLocation(), munger.getSourceLocation()
  202. );
  203. // Boolean.toString(runtimeTest)});
  204. }
  205. getMessageHandler().handleMessage(msg);
  206. }
  207. private boolean areTheSame(ISourceLocation locA, ISourceLocation locB) {
  208. if (locA == null) {
  209. return locB == null;
  210. }
  211. if (locB == null) {
  212. return false;
  213. }
  214. if (locA.getLine() != locB.getLine()) {
  215. return false;
  216. }
  217. File fA = locA.getSourceFile();
  218. File fB = locA.getSourceFile();
  219. if (fA == null) {
  220. return fB == null;
  221. }
  222. if (fB == null) {
  223. return false;
  224. }
  225. return fA.getName().equals(fB.getName());
  226. }
  227. /*
  228. * Ensure we report a nice source location - particular in the case where the source info is missing (binary weave).
  229. */
  230. private String beautifyLocation(ISourceLocation isl) {
  231. StringBuilder nice = new StringBuilder();
  232. if (isl == null || isl.getSourceFile() == null || isl.getSourceFile().getName().contains("no debug info available")) {
  233. nice.append("no debug info available");
  234. } else {
  235. // can't use File.getName() as this fails when a Linux box encounters a path created on Windows and vice-versa
  236. int takeFrom = isl.getSourceFile().getPath().lastIndexOf('/');
  237. if (takeFrom == -1) {
  238. takeFrom = isl.getSourceFile().getPath().lastIndexOf('\\');
  239. }
  240. int binary = isl.getSourceFile().getPath().lastIndexOf('!');
  241. if (binary != -1 && binary < takeFrom) {
  242. // we have been woven by a binary aspect
  243. String pathToBinaryLoc = isl.getSourceFile().getPath().substring(0, binary + 1);
  244. if (pathToBinaryLoc.contains(".jar")) {
  245. // only want to add the extra info if we're from a jar file
  246. int lastSlash = pathToBinaryLoc.lastIndexOf('/');
  247. if (lastSlash == -1) {
  248. lastSlash = pathToBinaryLoc.lastIndexOf('\\');
  249. }
  250. nice.append(pathToBinaryLoc.substring(lastSlash + 1));
  251. }
  252. }
  253. nice.append(isl.getSourceFile().getPath().substring(takeFrom + 1));
  254. if (isl.getLine() != 0) {
  255. nice.append(":").append(isl.getLine());
  256. }
  257. // if it's a binary file then also want to give the file name
  258. if (isl.getSourceFileName() != null) {
  259. nice.append("(from ").append(isl.getSourceFileName()).append(")");
  260. }
  261. }
  262. return nice.toString();
  263. }
  264. private static List<String> makeDefaultClasspath(String cp) {
  265. List<String> classPath = new ArrayList<>();
  266. classPath.addAll(getPathEntries(cp));
  267. classPath.addAll(getPathEntries(ClassPath.getClassPath()));
  268. return classPath;
  269. }
  270. private static List<String> getPathEntries(String s) {
  271. List<String> ret = new ArrayList<>();
  272. StringTokenizer tok = new StringTokenizer(s, File.pathSeparator);
  273. while (tok.hasMoreTokens()) {
  274. ret.add(tok.nextToken());
  275. }
  276. return ret;
  277. }
  278. public BcelWorld(List classPath, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  279. // this.aspectPath = new ClassPathManager(aspectPath, handler);
  280. this.classPath = new ClassPathManager(classPath, handler);
  281. setMessageHandler(handler);
  282. setCrossReferenceHandler(xrefHandler);
  283. // Tell BCEL to use us for resolving any classes
  284. delegate = this;
  285. }
  286. public BcelWorld(ClassPathManager cpm, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  287. classPath = cpm;
  288. setMessageHandler(handler);
  289. setCrossReferenceHandler(xrefHandler);
  290. // Tell BCEL to use us for resolving any classes
  291. delegate = this;
  292. }
  293. /**
  294. * Build a World from a ClassLoader, for LTW support
  295. *
  296. * @param loader
  297. * @param handler
  298. * @param xrefHandler
  299. */
  300. public BcelWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
  301. classPath = null;
  302. loaderRef = new BcelWeakClassLoaderReference(loader);
  303. setMessageHandler(handler);
  304. setCrossReferenceHandler(xrefHandler);
  305. // Tell BCEL to use us for resolving any classes
  306. // delegate = getClassLoaderRepositoryFor(loader);
  307. }
  308. public void ensureRepositorySetup() {
  309. if (delegate == null) {
  310. delegate = getClassLoaderRepositoryFor(loaderRef);
  311. }
  312. }
  313. public Repository getClassLoaderRepositoryFor(ClassLoaderReference loader) {
  314. if (bcelRepositoryCaching) {
  315. return new ClassLoaderRepository(loader);
  316. } else {
  317. return new NonCachingClassLoaderRepository(loader);
  318. }
  319. }
  320. public void addPath(String name) {
  321. classPath.addPath(name, this.getMessageHandler());
  322. }
  323. // ---- various interactions with bcel
  324. public static Type makeBcelType(UnresolvedType type) {
  325. return Type.getType(type.getErasureSignature());
  326. }
  327. static Type[] makeBcelTypes(UnresolvedType[] types) {
  328. Type[] ret = new Type[types.length];
  329. for (int i = 0, len = types.length; i < len; i++) {
  330. ret[i] = makeBcelType(types[i]);
  331. }
  332. return ret;
  333. }
  334. public static Type[] makeBcelTypes(String[] types) {
  335. if (types == null || types.length==0 ) {
  336. return null;
  337. }
  338. Type[] ret = new Type[types.length];
  339. for (int i=0, len=types.length; i<len; i++) {
  340. ret[i] = makeBcelType(types[i]);
  341. }
  342. return ret;
  343. }
  344. public static Type makeBcelType(String type) {
  345. return Type.getType(type);
  346. }
  347. static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) {
  348. String[] ret = new String[types.length];
  349. for (int i = 0, len = types.length; i < len; i++) {
  350. ret[i] = types[i].getName();
  351. }
  352. return ret;
  353. }
  354. public static UnresolvedType fromBcel(Type t) {
  355. return UnresolvedType.forSignature(t.getSignature());
  356. }
  357. static UnresolvedType[] fromBcel(Type[] ts) {
  358. UnresolvedType[] ret = new UnresolvedType[ts.length];
  359. for (int i = 0, len = ts.length; i < len; i++) {
  360. ret[i] = fromBcel(ts[i]);
  361. }
  362. return ret;
  363. }
  364. public ResolvedType resolve(Type t) {
  365. return resolve(fromBcel(t));
  366. }
  367. @Override
  368. protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
  369. String name = ty.getName();
  370. ensureAdvancedConfigurationProcessed();
  371. JavaClass jc = lookupJavaClass(classPath, name);
  372. if (jc == null) {
  373. // Anyone else to ask?
  374. if (typeDelegateResolvers != null) {
  375. for (TypeDelegateResolver tdr : typeDelegateResolvers) {
  376. ReferenceTypeDelegate delegate = tdr.getDelegate(ty);
  377. if (delegate != null) {
  378. return delegate;
  379. }
  380. }
  381. }
  382. return null;
  383. } else {
  384. return buildBcelDelegate(ty, jc, false, false);
  385. }
  386. }
  387. public BcelObjectType buildBcelDelegate(ReferenceType type, JavaClass jc, boolean artificial, boolean exposedToWeaver) {
  388. BcelObjectType ret = new BcelObjectType(type, jc, artificial, exposedToWeaver);
  389. return ret;
  390. }
  391. private JavaClass lookupJavaClass(ClassPathManager classPath, String name) {
  392. if (classPath == null) {
  393. try {
  394. ensureRepositorySetup();
  395. JavaClass jc = delegate.loadClass(name);
  396. if (trace.isTraceEnabled()) {
  397. trace.event("lookupJavaClass", this, new Object[] { name, jc });
  398. }
  399. return jc;
  400. } catch (ClassNotFoundException e) {
  401. if (trace.isTraceEnabled()) {
  402. trace.error("Unable to find class '" + name + "' in repository", e);
  403. }
  404. return null;
  405. }
  406. }
  407. ClassPathManager.ClassFile file = null;
  408. try {
  409. file = classPath.find(UnresolvedType.forName(name));
  410. if (file == null) {
  411. return null;
  412. }
  413. ClassParser parser = new ClassParser(file.getInputStream(), file.getPath());
  414. JavaClass jc = parser.parse();
  415. return jc;
  416. } catch (IOException ioe) {
  417. if (trace.isTraceEnabled()) {
  418. trace.error("IOException whilst processing class",ioe);
  419. }
  420. return null;
  421. } finally {
  422. if (file != null) {
  423. file.close();
  424. }
  425. }
  426. }
  427. public BcelObjectType addSourceObjectType(JavaClass jc, boolean artificial) {
  428. return addSourceObjectType(jc.getClassName(), jc, artificial);
  429. }
  430. public BcelObjectType addSourceObjectType(String classname, JavaClass jc, boolean artificial) {
  431. BcelObjectType ret = null;
  432. if (!jc.getClassName().equals(classname)) {
  433. throw new RuntimeException(jc.getClassName() + "!=" + classname);
  434. }
  435. String signature = UnresolvedType.forName(jc.getClassName()).getSignature();
  436. ResolvedType resolvedTypeFromTypeMap = typeMap.get(signature);
  437. if (resolvedTypeFromTypeMap != null && !(resolvedTypeFromTypeMap instanceof ReferenceType)) {
  438. // what on earth is it then? See pr 112243
  439. StringBuilder exceptionText = new StringBuilder();
  440. exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. ");
  441. exceptionText.append("Signature=[" + signature + "] Found=[" + resolvedTypeFromTypeMap + "] Class=[" + resolvedTypeFromTypeMap.getClass() + "]");
  442. throw new BCException(exceptionText.toString());
  443. }
  444. ReferenceType referenceTypeFromTypeMap = (ReferenceType) resolvedTypeFromTypeMap;
  445. if (referenceTypeFromTypeMap == null) {
  446. if (jc.isGeneric() && isInJava5Mode()) {
  447. ReferenceType rawType = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()), this);
  448. ret = buildBcelDelegate(rawType, jc, artificial, true);
  449. ReferenceType genericRefType = new ReferenceType(UnresolvedType.forGenericTypeSignature(signature,
  450. ret.getDeclaredGenericSignature()), this);
  451. rawType.setDelegate(ret);
  452. genericRefType.setDelegate(ret);
  453. rawType.setGenericType(genericRefType);
  454. typeMap.put(signature, rawType);
  455. } else {
  456. referenceTypeFromTypeMap = new ReferenceType(signature, this);
  457. ret = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
  458. typeMap.put(signature, referenceTypeFromTypeMap);
  459. }
  460. } else {
  461. ret = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
  462. }
  463. return ret;
  464. }
  465. public BcelObjectType addSourceObjectType(String classname, byte[] bytes, boolean artificial) {
  466. BcelObjectType retval = null;
  467. String signature = UnresolvedType.forName(classname).getSignature();
  468. ResolvedType resolvedTypeFromTypeMap = typeMap.get(signature);
  469. if (resolvedTypeFromTypeMap != null && !(resolvedTypeFromTypeMap instanceof ReferenceType)) {
  470. // what on earth is it then? See pr 112243
  471. StringBuilder exceptionText = new StringBuilder();
  472. exceptionText.append("Found invalid (not a ReferenceType) entry in the type map. ");
  473. exceptionText.append("Signature=[" + signature + "] Found=[" + resolvedTypeFromTypeMap + "] Class=[" + resolvedTypeFromTypeMap.getClass() + "]");
  474. throw new BCException(exceptionText.toString());
  475. }
  476. ReferenceType referenceTypeFromTypeMap = (ReferenceType) resolvedTypeFromTypeMap;
  477. if (referenceTypeFromTypeMap == null) {
  478. JavaClass jc = Utility.makeJavaClass(classname, bytes);
  479. if (jc.isGeneric() && isInJava5Mode()) {
  480. referenceTypeFromTypeMap = ReferenceType.fromTypeX(UnresolvedType.forRawTypeName(jc.getClassName()), this);
  481. retval = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
  482. ReferenceType genericRefType = new ReferenceType(UnresolvedType.forGenericTypeSignature(signature,
  483. retval.getDeclaredGenericSignature()), this);
  484. referenceTypeFromTypeMap.setDelegate(retval);
  485. genericRefType.setDelegate(retval);
  486. referenceTypeFromTypeMap.setGenericType(genericRefType);
  487. typeMap.put(signature, referenceTypeFromTypeMap);
  488. } else {
  489. referenceTypeFromTypeMap = new ReferenceType(signature, this);
  490. retval = buildBcelDelegate(referenceTypeFromTypeMap, jc, artificial, true);
  491. typeMap.put(signature, referenceTypeFromTypeMap);
  492. }
  493. } else {
  494. ReferenceTypeDelegate existingDelegate = referenceTypeFromTypeMap.getDelegate();
  495. if (!(existingDelegate instanceof BcelObjectType)) {
  496. throw new IllegalStateException("For " + classname + " should be BcelObjectType, but is " + existingDelegate.getClass());
  497. }
  498. retval = (BcelObjectType) existingDelegate;
  499. // Note1: If the type is already exposed to the weaver (retval.isExposedToWeaver()) then this is likely
  500. // to be a hotswap reweave so build a new delegate, don't accidentally use the old data.
  501. // Note2: Also seen when LTW and another agent precedes the AspectJ agent. Earlier in LTW
  502. // a type is resolved (and ends up in the typemap but not exposed to the weaver at that time)
  503. // then later LTW actually is attempted on this type. We end up here with different
  504. // bytes to the current delegate if the earlier agent has modified them. See PR488216
  505. // if (retval.isArtificial() || retval.isExposedToWeaver()) {
  506. retval = buildBcelDelegate(referenceTypeFromTypeMap, Utility.makeJavaClass(classname, bytes), artificial, true);
  507. // }
  508. }
  509. return retval;
  510. }
  511. void deleteSourceObjectType(UnresolvedType ty) {
  512. typeMap.remove(ty.getSignature());
  513. }
  514. public static Member makeFieldJoinPointSignature(LazyClassGen cg, FieldInstruction fi) {
  515. ConstantPool cpg = cg.getConstantPool();
  516. return MemberImpl.field(fi.getClassName(cpg),
  517. (fi.opcode == Constants.GETSTATIC || fi.opcode == Constants.PUTSTATIC) ? Modifier.STATIC : 0, fi.getName(cpg),
  518. fi.getSignature(cpg));
  519. }
  520. public Member makeJoinPointSignatureFromMethod(LazyMethodGen mg, MemberKind kind) {
  521. Member ret = mg.getMemberView();
  522. if (ret == null) {
  523. int mods = mg.getAccessFlags();
  524. if (mg.getEnclosingClass().isInterface()) {
  525. mods |= Modifier.INTERFACE;
  526. }
  527. return new ResolvedMemberImpl(kind, UnresolvedType.forName(mg.getClassName()), mods, fromBcel(mg.getReturnType()),
  528. mg.getName(), fromBcel(mg.getArgumentTypes()));
  529. } else {
  530. return ret;
  531. }
  532. }
  533. public Member makeJoinPointSignatureForMonitorEnter(LazyClassGen cg, InstructionHandle h) {
  534. return MemberImpl.monitorEnter();
  535. }
  536. public Member makeJoinPointSignatureForMonitorExit(LazyClassGen cg, InstructionHandle h) {
  537. return MemberImpl.monitorExit();
  538. }
  539. public Member makeJoinPointSignatureForArrayConstruction(LazyClassGen cg, InstructionHandle handle) {
  540. Instruction i = handle.getInstruction();
  541. ConstantPool cpg = cg.getConstantPool();
  542. Member retval = null;
  543. if (i.opcode == Constants.ANEWARRAY) {
  544. // ANEWARRAY arrayInstruction = (ANEWARRAY)i;
  545. Type ot = i.getType(cpg);
  546. UnresolvedType ut = fromBcel(ot);
  547. ut = UnresolvedType.makeArray(ut, 1);
  548. retval = MemberImpl.method(ut, Modifier.PUBLIC, UnresolvedType.VOID, "<init>", new ResolvedType[] { INT });
  549. } else if (i instanceof MULTIANEWARRAY) {
  550. MULTIANEWARRAY arrayInstruction = (MULTIANEWARRAY) i;
  551. UnresolvedType ut = null;
  552. short dimensions = arrayInstruction.getDimensions();
  553. ObjectType ot = arrayInstruction.getLoadClassType(cpg);
  554. if (ot != null) {
  555. ut = fromBcel(ot);
  556. ut = UnresolvedType.makeArray(ut, dimensions);
  557. } else {
  558. Type t = arrayInstruction.getType(cpg);
  559. ut = fromBcel(t);
  560. }
  561. ResolvedType[] parms = new ResolvedType[dimensions];
  562. for (int ii = 0; ii < dimensions; ii++) {
  563. parms[ii] = INT;
  564. }
  565. retval = MemberImpl.method(ut, Modifier.PUBLIC, UnresolvedType.VOID, "<init>", parms);
  566. } else if (i.opcode == Constants.NEWARRAY) {
  567. // NEWARRAY arrayInstruction = (NEWARRAY)i;
  568. Type ot = i.getType();
  569. UnresolvedType ut = fromBcel(ot);
  570. retval = MemberImpl.method(ut, Modifier.PUBLIC, UnresolvedType.VOID, "<init>", new ResolvedType[] { INT });
  571. } else {
  572. throw new BCException("Cannot create array construction signature for this non-array instruction:" + i);
  573. }
  574. return retval;
  575. }
  576. public Member makeJoinPointSignatureForMethodInvocation(LazyClassGen cg, InvokeInstruction ii) {
  577. ConstantPool cpg = cg.getConstantPool();
  578. String name = ii.getName(cpg);
  579. String declaring = ii.getClassName(cpg);
  580. UnresolvedType declaringType = null;
  581. String signature = ii.getSignature(cpg);
  582. // 307147
  583. if (name.startsWith("ajc$privMethod$")) {
  584. // The invoke is on a privileged accessor. These may be created for different
  585. // kinds of target, not necessarily just private methods. In bug 307147 it is
  586. // for a private method. This code is identifying the particular case in 307147
  587. try {
  588. declaringType = UnresolvedType.forName(declaring);
  589. String typeNameAsFoundInAccessorName = declaringType.getName().replace('.', '_');
  590. int indexInAccessorName = name.lastIndexOf(typeNameAsFoundInAccessorName);
  591. if (indexInAccessorName != -1) {
  592. String methodName = name.substring(indexInAccessorName+typeNameAsFoundInAccessorName.length()+1);
  593. ResolvedType resolvedDeclaringType = declaringType.resolve(this);
  594. ResolvedMember[] methods = resolvedDeclaringType.getDeclaredMethods();
  595. for (ResolvedMember method: methods) {
  596. if (method.getName().equals(methodName) && method.getSignature().equals(signature) && Modifier.isPrivate(method.getModifiers())) {
  597. return method;
  598. }
  599. }
  600. }
  601. } catch (Exception e) {
  602. // Remove this once confident above code isn't having unexpected side effects
  603. // Added 1.8.7
  604. e.printStackTrace();
  605. }
  606. }
  607. int modifier = (ii instanceof INVOKEINTERFACE) ? Modifier.INTERFACE
  608. : (ii.opcode == Constants.INVOKESTATIC) ? Modifier.STATIC : (ii.opcode == Constants.INVOKESPECIAL && !name
  609. .equals("<init>")) ? Modifier.PRIVATE : 0;
  610. // in Java 1.4 and after, static method call of super class within
  611. // subclass method appears
  612. // as declared by the subclass in the bytecode - but they are not
  613. // see #104212
  614. if (ii.opcode == Constants.INVOKESTATIC) {
  615. ResolvedType appearsDeclaredBy = resolve(declaring);
  616. // look for the method there
  617. for (Iterator<ResolvedMember> iterator = appearsDeclaredBy.getMethods(true, true); iterator.hasNext();) {
  618. ResolvedMember method = iterator.next();
  619. if (Modifier.isStatic(method.getModifiers())) {
  620. if (name.equals(method.getName()) && signature.equals(method.getSignature())) {
  621. // we found it
  622. declaringType = method.getDeclaringType();
  623. break;
  624. }
  625. }
  626. }
  627. }
  628. if (declaringType == null) {
  629. if (declaring.charAt(0) == '[') {
  630. declaringType = UnresolvedType.forSignature(declaring);
  631. } else {
  632. declaringType = UnresolvedType.forName(declaring);
  633. }
  634. }
  635. return MemberImpl.method(declaringType, modifier, name, signature);
  636. }
  637. @Override
  638. public String toString() {
  639. StringBuilder buf = new StringBuilder();
  640. buf.append("BcelWorld(");
  641. // buf.append(shadowMungerMap);
  642. buf.append(")");
  643. return buf.toString();
  644. }
  645. /**
  646. * Retrieve a bcel delegate for an aspect - this will return NULL if the delegate is an EclipseSourceType and not a
  647. * BcelObjectType - this happens quite often when incrementally compiling.
  648. */
  649. public static BcelObjectType getBcelObjectType(ResolvedType concreteAspect) {
  650. if (concreteAspect == null) {
  651. return null;
  652. }
  653. if (!(concreteAspect instanceof ReferenceType)) { // Might be Missing
  654. return null;
  655. }
  656. ReferenceTypeDelegate rtDelegate = ((ReferenceType) concreteAspect).getDelegate();
  657. if (rtDelegate instanceof BcelObjectType) {
  658. return (BcelObjectType) rtDelegate;
  659. } else {
  660. return null;
  661. }
  662. }
  663. public void tidyUp() {
  664. // At end of compile, close any open files so deletion of those archives
  665. // is possible
  666. classPath.closeArchives();
  667. typeMap.report();
  668. typeMap.demote(true);
  669. // ResolvedType.resetPrimitives();
  670. }
  671. // / The repository interface methods
  672. @Override
  673. public JavaClass findClass(String className) {
  674. return lookupJavaClass(classPath, className);
  675. }
  676. @Override
  677. public JavaClass loadClass(String className) throws ClassNotFoundException {
  678. return lookupJavaClass(classPath, className);
  679. }
  680. @Override
  681. public void storeClass(JavaClass clazz) {
  682. // doesn't need to do anything
  683. }
  684. @Override
  685. public void removeClass(JavaClass clazz) {
  686. throw new RuntimeException("Not implemented");
  687. }
  688. @Override
  689. public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
  690. throw new RuntimeException("Not implemented");
  691. }
  692. @Override
  693. public void clear() {
  694. delegate.clear();
  695. // throw new RuntimeException("Not implemented");
  696. }
  697. /**
  698. * The aim of this method is to make sure a particular type is 'ok'. Some operations on the delegate for a type modify it and
  699. * this method is intended to undo that... see pr85132
  700. */
  701. @Override
  702. public void validateType(UnresolvedType type) {
  703. ResolvedType result = typeMap.get(type.getSignature());
  704. if (result == null) {
  705. return; // We haven't heard of it yet
  706. }
  707. if (!result.isExposedToWeaver()) {
  708. return; // cant need resetting
  709. }
  710. result.ensureConsistent();
  711. // If we want to rebuild it 'from scratch' then:
  712. // ClassParser cp = new ClassParser(new
  713. // ByteArrayInputStream(newbytes),new String(cs));
  714. // try {
  715. // rt.setDelegate(makeBcelObjectType(rt,cp.parse(),true));
  716. // } catch (ClassFormatException e) {
  717. // e.printStackTrace();
  718. // } catch (IOException e) {
  719. // e.printStackTrace();
  720. // }
  721. }
  722. /**
  723. * Apply a single declare parents - return true if we change the type
  724. */
  725. private boolean applyDeclareParents(DeclareParents p, ResolvedType onType) {
  726. boolean didSomething = false;
  727. List<ResolvedType> newParents = p.findMatchingNewParents(onType, true);
  728. if (!newParents.isEmpty()) {
  729. didSomething = true;
  730. BcelObjectType classType = BcelWorld.getBcelObjectType(onType);
  731. // System.err.println("need to do declare parents for: " + onType);
  732. for (ResolvedType newParent : newParents) {
  733. // We set it here so that the imminent matching for ITDs can
  734. // succeed - we still haven't done the necessary changes to the class file
  735. // itself (like transform super calls) - that is done in
  736. // BcelTypeMunger.mungeNewParent()
  737. // classType.addParent(newParent);
  738. onType.addParent(newParent);
  739. ResolvedTypeMunger newParentMunger = new NewParentTypeMunger(newParent, p.getDeclaringType());
  740. newParentMunger.setSourceLocation(p.getSourceLocation());
  741. onType.addInterTypeMunger(new BcelTypeMunger(newParentMunger, getCrosscuttingMembersSet()
  742. .findAspectDeclaringParents(p)), false);
  743. }
  744. }
  745. return didSomething;
  746. }
  747. /**
  748. * Apply a declare @type - return true if we change the type
  749. */
  750. private boolean applyDeclareAtType(DeclareAnnotation decA, ResolvedType onType, boolean reportProblems) {
  751. boolean didSomething = false;
  752. if (decA.matches(onType)) {
  753. if (onType.hasAnnotation(decA.getAnnotation().getType())) {
  754. // already has it
  755. return false;
  756. }
  757. AnnotationAJ annoX = decA.getAnnotation();
  758. // check the annotation is suitable for the target
  759. boolean isOK = checkTargetOK(decA, onType, annoX);
  760. if (isOK) {
  761. didSomething = true;
  762. ResolvedTypeMunger newAnnotationTM = new AnnotationOnTypeMunger(annoX);
  763. newAnnotationTM.setSourceLocation(decA.getSourceLocation());
  764. onType.addInterTypeMunger(new BcelTypeMunger(newAnnotationTM, decA.getAspect().resolve(this)), false);
  765. decA.copyAnnotationTo(onType);
  766. }
  767. }
  768. return didSomething;
  769. }
  770. /**
  771. * Apply the specified declare @field construct to any matching fields in the specified type.
  772. * @param deca the declare annotation targeting fields
  773. * @param type the type to check for members matching the declare annotation
  774. * @return true if something matched and the type was modified
  775. */
  776. private boolean applyDeclareAtField(DeclareAnnotation deca, ResolvedType type) {
  777. boolean changedType = false;
  778. ResolvedMember[] fields = type.getDeclaredFields();
  779. for (ResolvedMember field: fields) {
  780. if (deca.matches(field, this)) {
  781. AnnotationAJ anno = deca.getAnnotation();
  782. if (!field.hasAnnotation(anno.getType())) {
  783. field.addAnnotation(anno);
  784. changedType=true;
  785. }
  786. }
  787. }
  788. return changedType;
  789. }
  790. /**
  791. * Checks for an @target() on the annotation and if found ensures it allows the annotation to be attached to the target type
  792. * that matched.
  793. */
  794. private boolean checkTargetOK(DeclareAnnotation decA, ResolvedType onType, AnnotationAJ annoX) {
  795. if (annoX.specifiesTarget()) {
  796. if ((onType.isAnnotation() && !annoX.allowedOnAnnotationType()) || (!annoX.allowedOnRegularType())) {
  797. return false;
  798. }
  799. }
  800. return true;
  801. }
  802. // Hmmm - very similar to the code in BcelWeaver.weaveParentTypeMungers -
  803. // this code
  804. // doesn't need to produce errors/warnings though as it won't really be
  805. // weaving.
  806. protected void weaveInterTypeDeclarations(ResolvedType onType) {
  807. List<DeclareParents> declareParentsList = getCrosscuttingMembersSet().getDeclareParents();
  808. if (onType.isRawType()) {
  809. onType = onType.getGenericType();
  810. }
  811. onType.clearInterTypeMungers();
  812. List<DeclareParents> decpToRepeat = new ArrayList<>();
  813. boolean aParentChangeOccurred = false;
  814. boolean anAnnotationChangeOccurred = false;
  815. // First pass - apply all decp mungers
  816. for (DeclareParents decp : declareParentsList) {
  817. boolean typeChanged = applyDeclareParents(decp, onType);
  818. if (typeChanged) {
  819. aParentChangeOccurred = true;
  820. } else { // Perhaps it would have matched if a 'dec @type' had
  821. // modified the type
  822. if (!decp.getChild().isStarAnnotation()) {
  823. decpToRepeat.add(decp);
  824. }
  825. }
  826. }
  827. // Still first pass - apply all dec @type mungers
  828. for (DeclareAnnotation decA : getCrosscuttingMembersSet().getDeclareAnnotationOnTypes()) {
  829. boolean typeChanged = applyDeclareAtType(decA, onType, true);
  830. if (typeChanged) {
  831. anAnnotationChangeOccurred = true;
  832. }
  833. }
  834. // apply declare @field
  835. for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnFields()) {
  836. if (applyDeclareAtField(deca,onType)) {
  837. anAnnotationChangeOccurred = true;
  838. }
  839. }
  840. while ((aParentChangeOccurred || anAnnotationChangeOccurred) && !decpToRepeat.isEmpty()) {
  841. anAnnotationChangeOccurred = aParentChangeOccurred = false;
  842. List<DeclareParents> decpToRepeatNextTime = new ArrayList<>();
  843. for (DeclareParents decp: decpToRepeat) {
  844. if (applyDeclareParents(decp, onType)) {
  845. aParentChangeOccurred = true;
  846. } else {
  847. decpToRepeatNextTime.add(decp);
  848. }
  849. }
  850. for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnTypes()) {
  851. if (applyDeclareAtType(deca, onType, false)) {
  852. anAnnotationChangeOccurred = true;
  853. }
  854. }
  855. for (DeclareAnnotation deca: getCrosscuttingMembersSet().getDeclareAnnotationOnFields()) {
  856. if (applyDeclareAtField(deca, onType)) {
  857. anAnnotationChangeOccurred = true;
  858. }
  859. }
  860. decpToRepeat = decpToRepeatNextTime;
  861. }
  862. }
  863. @Override
  864. public IWeavingSupport getWeavingSupport() {
  865. return bcelWeavingSupport;
  866. }
  867. @Override
  868. public void reportCheckerMatch(Checker checker, Shadow shadow) {
  869. IMessage iMessage = new Message(checker.getMessage(shadow), shadow.toString(), checker.isError() ? IMessage.ERROR
  870. : IMessage.WARNING, shadow.getSourceLocation(), null, new ISourceLocation[] { checker.getSourceLocation() }, true,
  871. 0, -1, -1);
  872. getMessageHandler().handleMessage(iMessage);
  873. if (getCrossReferenceHandler() != null) {
  874. getCrossReferenceHandler()
  875. .addCrossReference(
  876. checker.getSourceLocation(),
  877. shadow.getSourceLocation(),
  878. (checker.isError() ? IRelationship.Kind.DECLARE_ERROR.getName() : IRelationship.Kind.DECLARE_WARNING
  879. .getName()), false);
  880. }
  881. if (getModel() != null) {
  882. AsmRelationshipProvider.addDeclareErrorOrWarningRelationship(getModelAsAsmManager(), shadow, checker);
  883. }
  884. }
  885. public AsmManager getModelAsAsmManager() {
  886. return (AsmManager) getModel(); // For now... always an AsmManager in a bcel environment
  887. }
  888. void raiseError(String message) {
  889. getMessageHandler().handleMessage(MessageUtil.error(message));
  890. }
  891. /**
  892. * These are aop.xml files that can be used to alter the aspects that actually apply from those passed in - and also their scope
  893. * of application to other files in the system.
  894. *
  895. * @param xmlFiles list of File objects representing any aop.xml files passed in to configure the build process
  896. */
  897. public void setXmlFiles(List<File> xmlFiles) {
  898. if (!isXmlConfiguredWorld && !xmlFiles.isEmpty()) {
  899. raiseError("xml configuration files only supported by the compiler when -xmlConfigured option specified");
  900. return;
  901. }
  902. if (!xmlFiles.isEmpty()) {
  903. xmlConfiguration = new WeavingXmlConfig(this, WeavingXmlConfig.MODE_COMPILE);
  904. }
  905. for (File xmlfile : xmlFiles) {
  906. try {
  907. Definition d = DocumentParser.parse(xmlfile.toURI().toURL());
  908. xmlConfiguration.add(d);
  909. } catch (MalformedURLException e) {
  910. raiseError("Unexpected problem processing XML config file '" + xmlfile.getName() + "' :" + e.getMessage());
  911. } catch (Exception e) {
  912. raiseError("Unexpected problem processing XML config file '" + xmlfile.getName() + "' :" + e.getMessage());
  913. }
  914. }
  915. }
  916. /**
  917. * Add a scoped aspects where the scoping was defined in an aop.xml file and this world is being used in a LTW configuration
  918. */
  919. public void addScopedAspect(String name, String scope) {
  920. this.isXmlConfiguredWorld = true;
  921. if (xmlConfiguration == null) {
  922. xmlConfiguration = new WeavingXmlConfig(this, WeavingXmlConfig.MODE_LTW);
  923. }
  924. xmlConfiguration.addScopedAspect(name, scope);
  925. }
  926. public void setXmlConfigured(boolean b) {
  927. this.isXmlConfiguredWorld = b;
  928. }
  929. @Override
  930. public boolean isXmlConfigured() {
  931. return isXmlConfiguredWorld && xmlConfiguration != null;
  932. }
  933. public WeavingXmlConfig getXmlConfiguration() {
  934. return xmlConfiguration;
  935. }
  936. @Override
  937. public boolean isAspectIncluded(ResolvedType aspectType) {
  938. if (!isXmlConfigured()) {
  939. return true;
  940. }
  941. return xmlConfiguration.specifiesInclusionOfAspect(aspectType.getName());
  942. }
  943. @Override
  944. public TypePattern getAspectScope(ResolvedType declaringType) {
  945. return xmlConfiguration.getScopeFor(declaringType.getName());
  946. }
  947. @Override
  948. public boolean hasUnsatisfiedDependency(ResolvedType aspectType) {
  949. String aspectName = aspectType.getName();
  950. if (aspectType.hasAnnotations()) {
  951. AnnotationAJ[] annos = aspectType.getAnnotations();
  952. for (AnnotationAJ anno: annos) {
  953. if (anno.getTypeName().equals("org.aspectj.lang.annotation.RequiredTypes")) {
  954. String values = anno.getStringFormOfValue("value"); // Example: "[A,org.foo.Bar]"
  955. if (values != null && values.length() > 2) {
  956. values = values.substring(1,values.length()-1);
  957. StringTokenizer tokenizer = new StringTokenizer(values,",");
  958. boolean anythingMissing = false;
  959. while (tokenizer.hasMoreElements()) {
  960. String requiredTypeName = tokenizer.nextToken();
  961. ResolvedType rt = resolve(UnresolvedType.forName(requiredTypeName));
  962. if (rt.isMissing()) {
  963. if (!getMessageHandler().isIgnoring(IMessage.INFO)) {
  964. getMessageHandler().handleMessage(
  965. MessageUtil.info("deactivating aspect '" + aspectName + "' as it requires type '"
  966. + requiredTypeName + "' which cannot be found on the classpath"));
  967. }
  968. anythingMissing = true;
  969. if (aspectRequiredTypes == null) {
  970. aspectRequiredTypes = new HashMap<>();
  971. }
  972. // Record that it has an invalid type reference
  973. aspectRequiredTypes.put(aspectName,requiredTypeName);
  974. }
  975. }
  976. if (anythingMissing) {
  977. return true;
  978. }
  979. else {
  980. return false;
  981. }
  982. }
  983. else {
  984. // no value specified for annotation
  985. return false;
  986. }
  987. }
  988. }
  989. }
  990. if (aspectRequiredTypes == null) {
  991. // no aspects require anything, so there can be no unsatisfied dependencies
  992. return false;
  993. }
  994. if (!aspectRequiredTypesProcessed.contains(aspectName)) {
  995. String requiredTypeName = aspectRequiredTypes.get(aspectName);
  996. if (requiredTypeName==null) {
  997. aspectRequiredTypesProcessed.add(aspectName);
  998. return false;
  999. } else {
  1000. ResolvedType rt = resolve(UnresolvedType.forName(requiredTypeName));
  1001. if (!rt.isMissing()) {
  1002. aspectRequiredTypesProcessed.add(aspectName);
  1003. aspectRequiredTypes.remove(aspectName);
  1004. return false;
  1005. } else {
  1006. if (!getMessageHandler().isIgnoring(IMessage.INFO)) {
  1007. getMessageHandler().handleMessage(
  1008. MessageUtil.info("deactivating aspect '" + aspectName + "' as it requires type '"
  1009. + requiredTypeName + "' which cannot be found on the classpath"));
  1010. }
  1011. aspectRequiredTypesProcessed.add(aspectName);
  1012. return true;
  1013. }
  1014. }
  1015. }
  1016. return aspectRequiredTypes.containsKey(aspectName);
  1017. }
  1018. private List<String> aspectRequiredTypesProcessed = new ArrayList<>();
  1019. private Map<String, String> aspectRequiredTypes = null;
  1020. public void addAspectRequires(String aspectClassName, String requiredType) {
  1021. if (aspectRequiredTypes == null) {
  1022. aspectRequiredTypes = new HashMap<>();
  1023. }
  1024. aspectRequiredTypes.put(aspectClassName,requiredType);
  1025. }
  1026. /**
  1027. * A WeavingXmlConfig is initially a collection of definitions from XML files - once the world is ready and weaving is running
  1028. * it will initialize and transform those definitions into an optimized set of values (eg. resolve type patterns and string
  1029. * names to real entities). It can then answer questions quickly: (1) is this aspect included in the weaving? (2) Is there a
  1030. * scope specified for this aspect and does it include type X?
  1031. *
  1032. */
  1033. static class WeavingXmlConfig {
  1034. final static int MODE_COMPILE = 1;
  1035. final static int MODE_LTW = 2;
  1036. private int mode;
  1037. private boolean initialized = false; // Lazily done
  1038. private List<Definition> definitions = new ArrayList<>();
  1039. private List<String> resolvedIncludedAspects = new ArrayList<>();
  1040. private Map<String, TypePattern> scopes = new HashMap<>();
  1041. // these are not set for LTW mode (exclusion of these fast match patterns is handled before the weaver/world are used)
  1042. private List<String> includedFastMatchPatterns = Collections.emptyList();
  1043. private List<TypePattern> includedPatterns = Collections.emptyList();
  1044. private List<String> excludedFastMatchPatterns = Collections.emptyList();
  1045. private List<TypePattern> excludedPatterns = Collections.emptyList();
  1046. private BcelWorld world;
  1047. public WeavingXmlConfig(BcelWorld bcelWorld, int mode) {
  1048. this.world = bcelWorld;
  1049. this.mode = mode;
  1050. }
  1051. public void add(Definition d) {
  1052. definitions.add(d);
  1053. }
  1054. public void addScopedAspect(String aspectName, String scope) {
  1055. ensureInitialized();
  1056. resolvedIncludedAspects.add(aspectName);
  1057. try {
  1058. TypePattern scopePattern = new PatternParser(scope).parseTypePattern();
  1059. scopePattern.resolve(world);
  1060. scopes.put(aspectName, scopePattern);
  1061. if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
  1062. world.getMessageHandler().handleMessage(
  1063. MessageUtil.info("Aspect '" + aspectName + "' is scoped to apply against types matching pattern '"
  1064. + scopePattern + "'"));
  1065. }
  1066. } catch (Exception e) {
  1067. world.getMessageHandler().handleMessage(
  1068. MessageUtil.error("Unable to parse scope as type pattern. Scope was '" + scope + "': " + e.getMessage()));
  1069. }
  1070. }
  1071. public void ensureInitialized() {
  1072. if (!initialized) {
  1073. try {
  1074. resolvedIncludedAspects = new ArrayList<>();
  1075. // Process the definitions into something more optimal
  1076. for (Definition definition : definitions) {
  1077. List<String> aspectNames = definition.getAspectClassNames();
  1078. for (String name : aspectNames) {
  1079. resolvedIncludedAspects.add(name);
  1080. // TODO check for existence?
  1081. // ResolvedType resolvedAspect = resolve(UnresolvedType.forName(name));
  1082. // if (resolvedAspect.isMissing()) {
  1083. // // ERROR
  1084. // } else {
  1085. // resolvedIncludedAspects.add(resolvedAspect);
  1086. // }
  1087. String scope = definition.getScopeForAspect(name);
  1088. if (scope != null) {
  1089. // Resolve the type pattern
  1090. try {
  1091. TypePattern scopePattern = new PatternParser(scope).parseTypePattern();
  1092. scopePattern.resolve(world);
  1093. scopes.put(name, scopePattern);
  1094. if (!world.getMessageHandler().isIgnoring(IMessage.INFO)) {
  1095. world.getMessageHandler().handleMessage(
  1096. MessageUtil.info("Aspect '" + name
  1097. + "' is scoped to apply against types matching pattern '"
  1098. + scopePattern.toString() + "'"));
  1099. }
  1100. } catch (Exception e) {
  1101. // TODO definitions should remember which file they came from, for inclusion in this message
  1102. world.getMessageHandler().handleMessage(
  1103. MessageUtil.error("Unable to parse scope as type pattern. Scope was '" + scope + "': "
  1104. + e.getMessage()));
  1105. }
  1106. }
  1107. }
  1108. try {
  1109. List<String> includePatterns = definition.getIncludePatterns();
  1110. if (includePatterns.size() > 0) {
  1111. includedPatterns = new ArrayList<>();
  1112. includedFastMatchPatterns = new ArrayList<>();
  1113. }
  1114. for (String includePattern : includePatterns) {
  1115. if (includePattern.endsWith("..*")) {
  1116. // from 'blah.blah.blah..*' leave the 'blah.blah.blah.'
  1117. includedFastMatchPatterns.add(includePattern.substring(0, includePattern.length() - 2));
  1118. } else {
  1119. TypePattern includedPattern = new PatternParser(includePattern).parseTypePattern();
  1120. includedPatterns.add(includedPattern);
  1121. }
  1122. }
  1123. List<String> excludePatterns = definition.getExcludePatterns();
  1124. if (excludePatterns.size() > 0) {
  1125. excludedPatterns = new ArrayList<>();
  1126. excludedFastMatchPatterns = new ArrayList<>();
  1127. }
  1128. for (String excludePattern : excludePatterns) {
  1129. if (excludePattern.endsWith("..*")) {
  1130. // from 'blah.blah.blah..*' leave the 'blah.blah.blah.'
  1131. excludedFastMatchPatterns.add(excludePattern.substring(0, excludePattern.length() - 2));
  1132. } else {
  1133. TypePattern excludedPattern = new PatternParser(excludePattern).parseTypePattern();
  1134. excludedPatterns.add(excludedPattern);
  1135. }
  1136. }
  1137. } catch (ParserException pe) {
  1138. // TODO definitions should remember which file they came from, for inclusion in this message
  1139. world.getMessageHandler().handleMessage(
  1140. MessageUtil.error("Unable to parse type pattern: " + pe.getMessage()));
  1141. }
  1142. }
  1143. } finally {
  1144. initialized = true;
  1145. }
  1146. }
  1147. }
  1148. public boolean specifiesInclusionOfAspect(String name) {
  1149. ensureInitialized();
  1150. return resolvedIncludedAspects.contains(name);
  1151. }
  1152. public TypePattern getScopeFor(String name) {
  1153. return scopes.get(name);
  1154. }
  1155. /**
  1156. * Checks if a given type is to be excluded from weaving.
  1157. * <p>
  1158. * For LTW, the development guide (<i>docs/devguide/ltw.adoc</i>) says:
  1159. * <p>
  1160. * <i>"The set of types to be woven are those types matched by at least one weaver {@code include} element and not
  1161. * matched by any weaver {@code exclude} element. If there are no weaver include statements, then all non-excluded
  1162. * types are included."</i>
  1163. * <p>
  1164. * In CTW mode, we cannot quite follow the same rules for exclusion as used for LTW: If the weaver is seeing it
  1165. * during this kind of build, the type is implicitly included. So all we should check for is exclusion.
  1166. *
  1167. * @param type resolved type to be checked
  1168. *
  1169. * @return Always false in LTW mode. In CTW mode true for excluded types, false otherwise.
  1170. */
  1171. public boolean excludesType(ResolvedType type) {
  1172. if (mode == MODE_LTW) {
  1173. return false;
  1174. }
  1175. String typename = type.getName();
  1176. boolean excluded = false;
  1177. for (String excludedPattern : excludedFastMatchPatterns) {
  1178. if (typename.startsWith(excludedPattern)) {
  1179. excluded = true;
  1180. break;
  1181. }
  1182. }
  1183. if (!excluded) {
  1184. for (TypePattern excludedPattern : excludedPatterns) {
  1185. if (excludedPattern.matchesStatically(type)) {
  1186. excluded = true;
  1187. break;
  1188. }
  1189. }
  1190. }
  1191. return excluded;
  1192. }
  1193. }
  1194. @Override
  1195. public TypeMap getTypeMap() {
  1196. return typeMap;
  1197. }
  1198. @Override
  1199. public boolean isLoadtimeWeaving() {
  1200. return false;
  1201. }
  1202. public void addTypeDelegateResolver(TypeDelegateResolver typeDelegateResolver) {
  1203. if (typeDelegateResolvers == null) {
  1204. typeDelegateResolvers = new ArrayList<>();
  1205. }
  1206. typeDelegateResolvers.add(typeDelegateResolver);
  1207. }
  1208. @Override
  1209. public void classWriteEvent(char[][] compoundName) {
  1210. typeMap.classWriteEvent(new String(CharOperation.concatWith(compoundName, '.')));
  1211. }
  1212. /**
  1213. * Force demote a type.
  1214. */
  1215. public void demote(ResolvedType type) {
  1216. typeMap.demote(type);
  1217. }
  1218. }