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.

WeavingAdaptor.java 31KB

11 years ago
13 years ago
18 years ago
14 years ago
18 years ago
18 years ago
15 years ago
11 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
14 years ago
14 years ago
15 years ago
13 years ago
11 years ago
11 years ago
15 years ago
11 years ago
15 years ago
15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. /* *******************************************************************
  2. * Copyright (c) 2004 IBM Corporation
  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. * Matthew Webster, Adrian Colyer, John Kew + Lyor Goldstein (caching)
  11. * Martin Lippert initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.weaver.tools;
  14. import java.io.File;
  15. import java.io.FileOutputStream;
  16. import java.io.IOException;
  17. import java.io.PrintWriter;
  18. import java.net.URL;
  19. import java.net.URLClassLoader;
  20. import java.security.ProtectionDomain;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.HashMap;
  24. import java.util.HashSet;
  25. import java.util.Iterator;
  26. import java.util.LinkedList;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.Properties;
  30. import java.util.Set;
  31. import java.util.StringTokenizer;
  32. import org.aspectj.bridge.AbortException;
  33. import org.aspectj.bridge.IMessage;
  34. import org.aspectj.bridge.IMessage.Kind;
  35. import org.aspectj.bridge.IMessageContext;
  36. import org.aspectj.bridge.IMessageHandler;
  37. import org.aspectj.bridge.IMessageHolder;
  38. import org.aspectj.bridge.Message;
  39. import org.aspectj.bridge.MessageHandler;
  40. import org.aspectj.bridge.MessageUtil;
  41. import org.aspectj.bridge.MessageWriter;
  42. import org.aspectj.bridge.Version;
  43. import org.aspectj.bridge.WeaveMessage;
  44. import org.aspectj.util.FileUtil;
  45. import org.aspectj.util.LangUtil;
  46. import org.aspectj.weaver.IClassFileProvider;
  47. import org.aspectj.weaver.IUnwovenClassFile;
  48. import org.aspectj.weaver.IWeaveRequestor;
  49. import org.aspectj.weaver.World;
  50. import org.aspectj.weaver.bcel.BcelObjectType;
  51. import org.aspectj.weaver.bcel.BcelWeaver;
  52. import org.aspectj.weaver.bcel.BcelWorld;
  53. import org.aspectj.weaver.bcel.UnwovenClassFile;
  54. import org.aspectj.weaver.tools.cache.CachedClassEntry;
  55. import org.aspectj.weaver.tools.cache.CachedClassReference;
  56. import org.aspectj.weaver.tools.cache.SimpleCache;
  57. import org.aspectj.weaver.tools.cache.SimpleCacheFactory;
  58. import org.aspectj.weaver.tools.cache.WeavedClassCache;
  59. // OPTIMIZE add guards for all the debug/info/etc
  60. /**
  61. * This adaptor allows the AspectJ compiler to be embedded in an existing system to facilitate load-time weaving. It provides an
  62. * interface for a weaving class loader to provide a classpath to be woven by a set of aspects. A callback is supplied to allow a
  63. * class loader to define classes generated by the compiler during the weaving process.
  64. * <p>
  65. * A weaving class loader should create a <code>WeavingAdaptor</code> before any classes are defined, typically during construction.
  66. * The set of aspects passed to the adaptor is fixed for the lifetime of the adaptor although the classpath can be augmented. A
  67. * system property can be set to allow verbose weaving messages to be written to the console.
  68. *
  69. */
  70. public class WeavingAdaptor implements IMessageContext {
  71. /**
  72. * System property used to turn on verbose weaving messages
  73. */
  74. public static final String WEAVING_ADAPTOR_VERBOSE = "aj.weaving.verbose";
  75. public static final String SHOW_WEAVE_INFO_PROPERTY = "org.aspectj.weaver.showWeaveInfo";
  76. public static final String TRACE_MESSAGES_PROPERTY = "org.aspectj.tracing.messages";
  77. private final static String ASPECTJ_BASE_PACKAGE = "org.aspectj.";
  78. private final static String PACKAGE_INITIAL_CHARS = ASPECTJ_BASE_PACKAGE.charAt(0) + "sj";
  79. private boolean enabled = false;
  80. protected boolean verbose = getVerbose();
  81. protected BcelWorld bcelWorld;
  82. protected BcelWeaver weaver;
  83. private IMessageHandler messageHandler;
  84. private WeavingAdaptorMessageHolder messageHolder;
  85. private boolean abortOnError = false;
  86. protected GeneratedClassHandler generatedClassHandler;
  87. protected Map<String, IUnwovenClassFile> generatedClasses = new HashMap<>();
  88. public BcelObjectType delegateForCurrentClass; // lazily initialized, should be used to prevent parsing bytecode multiple
  89. // times
  90. protected ProtectionDomain activeProtectionDomain;
  91. private boolean haveWarnedOnJavax = false;
  92. protected WeavedClassCache cache;
  93. private int weavingSpecialTypes = 0;
  94. private static final int INITIALIZED = 0x1;
  95. private static final int WEAVE_JAVA_PACKAGE = 0x2;
  96. private static final int WEAVE_JAVAX_PACKAGE = 0x4;
  97. private static Trace trace = TraceFactory.getTraceFactory().getTrace(WeavingAdaptor.class);
  98. protected WeavingAdaptor() {
  99. }
  100. /**
  101. * Construct a WeavingAdaptor with a reference to a weaving class loader. The adaptor will automatically search the class loader
  102. * hierarchy to resolve classes. The adaptor will also search the hierarchy for WeavingClassLoader instances to determine the
  103. * set of aspects to be used for weaving.
  104. *
  105. * @param loader instance of <code>ClassLoader</code>
  106. */
  107. public WeavingAdaptor(WeavingClassLoader loader) {
  108. // System.err.println("? WeavingAdaptor.<init>(" + loader +"," + aspectURLs.length + ")");
  109. generatedClassHandler = loader;
  110. init((ClassLoader)loader, getFullClassPath((ClassLoader) loader), getFullAspectPath((ClassLoader) loader/* ,aspectURLs */));
  111. }
  112. /**
  113. * Construct a WeavingAdaptor with a reference to a <code>GeneratedClassHandler</code>, a full search path for resolving classes
  114. * and a complete set of aspects. The search path must include classes loaded by the class loader constructing the
  115. * WeavingAdaptor and all its parents in the hierarchy.
  116. *
  117. * @param handler <code>GeneratedClassHandler</code>
  118. * @param classURLs the URLs from which to resolve classes
  119. * @param aspectURLs the aspects used to weave classes defined by this class loader
  120. */
  121. public WeavingAdaptor(GeneratedClassHandler handler, URL[] classURLs, URL[] aspectURLs) {
  122. // System.err.println("? WeavingAdaptor.<init>()");
  123. generatedClassHandler = handler;
  124. init(null, FileUtil.makeClasspath(classURLs), FileUtil.makeClasspath(aspectURLs));
  125. }
  126. protected List<String> getFullClassPath(ClassLoader loader) {
  127. List<String> list = new LinkedList<>();
  128. for (; loader != null; loader = loader.getParent()) {
  129. if (loader instanceof URLClassLoader) {
  130. URL[] urls = ((URLClassLoader) loader).getURLs();
  131. list.addAll(0, FileUtil.makeClasspath(urls));
  132. } else {
  133. warn("cannot determine classpath");
  134. }
  135. }
  136. // On Java9 it is possible to fail to find a URLClassLoader from which to derive a suitable classpath
  137. // For now we can determine it from the java.class.path:
  138. if (LangUtil.is9VMOrGreater()) {
  139. list.add(0, LangUtil.getJrtFsFilePath());
  140. List<String> javaClassPathEntries = makeClasspath(System.getProperty("java.class.path"));
  141. for (int i=javaClassPathEntries.size()-1;i>=0;i--) {
  142. String javaClassPathEntry = javaClassPathEntries.get(i);
  143. if (!list.contains(javaClassPathEntry)) {
  144. list.add(0,javaClassPathEntry);
  145. }
  146. }
  147. }
  148. // On Java9 the sun.boot.class.path won't be set. System classes accessible through JRT filesystem
  149. list.addAll(0, makeClasspath(System.getProperty("sun.boot.class.path")));
  150. return list;
  151. }
  152. private List<String> getFullAspectPath(ClassLoader loader) {
  153. List<String> list = new LinkedList<>();
  154. for (; loader != null; loader = loader.getParent()) {
  155. if (loader instanceof WeavingClassLoader) {
  156. URL[] urls = ((WeavingClassLoader) loader).getAspectURLs();
  157. list.addAll(0, FileUtil.makeClasspath(urls));
  158. }
  159. }
  160. return list;
  161. }
  162. private static boolean getVerbose() {
  163. try {
  164. return Boolean.getBoolean(WEAVING_ADAPTOR_VERBOSE);
  165. } catch (Throwable t) {
  166. // security exception
  167. return false;
  168. }
  169. }
  170. /**
  171. * Initialize the WeavingAdapter
  172. * @param loader ClassLoader used by this adapter; which can be null
  173. * @param classPath classpath of this adapter
  174. * @param aspectPath list of aspect paths
  175. */
  176. private void init(ClassLoader loader, List<String> classPath, List<String> aspectPath) {
  177. abortOnError = true;
  178. createMessageHandler();
  179. info("using classpath: " + classPath);
  180. info("using aspectpath: " + aspectPath);
  181. bcelWorld = new BcelWorld(classPath, messageHandler, null);
  182. bcelWorld.setXnoInline(false);
  183. bcelWorld.getLint().loadDefaultProperties();
  184. bcelWorld.setBehaveInJava5Way(true);
  185. weaver = new BcelWeaver(bcelWorld);
  186. registerAspectLibraries(aspectPath);
  187. initializeCache(loader, aspectPath, null, getMessageHandler());
  188. enabled = true;
  189. }
  190. /**
  191. * If the cache is enabled, initialize it and swap out the existing classhandler
  192. * for the caching one -
  193. *
  194. * @param loader classloader for this adapter, may be null
  195. * @param aspects List of strings representing aspects managed by the adapter; these could be urls or classnames
  196. * @param existingClassHandler current class handler
  197. * @param myMessageHandler current message handler
  198. */
  199. protected void initializeCache(ClassLoader loader, List<String> aspects, GeneratedClassHandler existingClassHandler, IMessageHandler myMessageHandler) {
  200. if (WeavedClassCache.isEnabled()) {
  201. cache = WeavedClassCache.createCache(loader, aspects, existingClassHandler, myMessageHandler);
  202. // Wrap the existing class handler so that any generated classes are also cached
  203. if (cache != null) {
  204. this.generatedClassHandler = cache.getCachingClassHandler();
  205. }
  206. }
  207. }
  208. protected void createMessageHandler() {
  209. messageHolder = new WeavingAdaptorMessageHolder(new PrintWriter(System.err));
  210. messageHandler = messageHolder;
  211. if (verbose) {
  212. messageHandler.dontIgnore(IMessage.INFO);
  213. }
  214. if (Boolean.getBoolean(SHOW_WEAVE_INFO_PROPERTY)) {
  215. messageHandler.dontIgnore(IMessage.WEAVEINFO);
  216. }
  217. info("AspectJ Weaver Version " + Version.getText() + " built on " + Version.getTimeText()); //$NON-NLS-1$
  218. }
  219. protected IMessageHandler getMessageHandler() {
  220. return messageHandler;
  221. }
  222. public IMessageHolder getMessageHolder() {
  223. return messageHolder;
  224. }
  225. protected void setMessageHandler(IMessageHandler mh) {
  226. if (mh instanceof ISupportsMessageContext) {
  227. ISupportsMessageContext smc = (ISupportsMessageContext) mh;
  228. smc.setMessageContext(this);
  229. }
  230. if (mh != messageHolder) {
  231. messageHolder.setDelegate(mh);
  232. }
  233. messageHolder.flushMessages();
  234. }
  235. protected void disable() {
  236. if (trace.isTraceEnabled()) {
  237. trace.enter("disable", this);
  238. }
  239. enabled = false;
  240. messageHolder.flushMessages();
  241. if (trace.isTraceEnabled()) {
  242. trace.exit("disable");
  243. }
  244. }
  245. protected void enable() {
  246. enabled = true;
  247. messageHolder.flushMessages();
  248. }
  249. protected boolean isEnabled() {
  250. return enabled;
  251. }
  252. /**
  253. * Appends URL to path used by the WeavingAdptor to resolve classes
  254. *
  255. * @param url to be appended to search path
  256. */
  257. public void addURL(URL url) {
  258. File libFile = new File(url.getPath());
  259. try {
  260. weaver.addLibraryJarFile(libFile);
  261. } catch (IOException ex) {
  262. warn("bad library: '" + libFile + "'");
  263. }
  264. }
  265. /**
  266. * Weave a class using aspects previously supplied to the adaptor.
  267. *
  268. * @param name the name of the class
  269. * @param bytes the class bytes
  270. * @return the woven bytes
  271. * @exception IOException weave failed
  272. */
  273. public byte[] weaveClass(String name, byte[] bytes) throws IOException {
  274. return weaveClass(name, bytes, false);
  275. }
  276. // Track if the weaver is already running on this thread - don't allow re-entrant calls
  277. private ThreadLocal<Boolean> weaverRunning = new ThreadLocal<Boolean>() {
  278. @Override
  279. protected Boolean initialValue() {
  280. return Boolean.FALSE;
  281. }
  282. };
  283. /**
  284. * Weave a class using aspects previously supplied to the adaptor.
  285. *
  286. * @param name the name of the class in the internal form of fully qualified class and interface names as defined
  287. * in <i>The Java Virtual Machine Specification</i>. For example, <code>"java/util/List"</code>.
  288. * @param bytes the input byte buffer in class file format - must not be modified
  289. * @param mustWeave if true then this class <i>must</i> get woven (used for concrete aspects generated from XML)
  290. *
  291. * @return a well-formed class file buffer (the weaving result), or {@code null} if no weaving was performed
  292. *
  293. * @throws IOException weave failed
  294. *
  295. * @see java.lang.instrument.ClassFileTransformer#transform(ClassLoader, String, Class, ProtectionDomain, byte[])
  296. */
  297. public byte[] weaveClass(String name, final byte[] bytes, boolean mustWeave) throws IOException {
  298. if (trace == null) {
  299. // Pr231945: we are likely to be under tomcat and ENABLE_CLEAR_REFERENCES hasn't been set
  300. System.err
  301. .println("AspectJ Weaver cannot continue to weave, static state has been cleared. Are you under Tomcat? In order to weave '"
  302. + name
  303. + "' during shutdown, 'org.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false' must be set (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=231945).");
  304. return null;
  305. }
  306. if (weaverRunning.get()) {
  307. // System.out.println("AJC: avoiding re-entrant call to transform " + name);
  308. return null;
  309. }
  310. try {
  311. byte[] newBytes = null;
  312. weaverRunning.set(true);
  313. if (trace.isTraceEnabled()) {
  314. trace.enter("weaveClass", this, new Object[] { name, bytes });
  315. }
  316. if (!enabled) {
  317. if (trace.isTraceEnabled()) {
  318. trace.exit("weaveClass", false);
  319. }
  320. return null;
  321. }
  322. boolean debugOn = !messageHandler.isIgnoring(Message.DEBUG);
  323. try {
  324. delegateForCurrentClass = null;
  325. name = name.replace('/', '.');
  326. if (couldWeave(name, bytes)) {
  327. if (accept(name, bytes)) {
  328. // Determine if we have the weaved class cached
  329. CachedClassReference cacheKey = null;
  330. if (cache != null && !mustWeave) {
  331. cacheKey = cache.createCacheKey(name, bytes);
  332. CachedClassEntry entry = cache.get(cacheKey, bytes);
  333. if (entry != null) {
  334. // If the entry has been explicitly ignored
  335. // return the original bytes
  336. if (entry.isIgnored()) {
  337. return null;
  338. }
  339. return entry.getBytes();
  340. }
  341. }
  342. // TODO @AspectJ problem
  343. // Annotation style aspects need to be included regardless in order to get
  344. // a valid aspectOf()/hasAspect() generated in them. However - if they are excluded
  345. // (via include/exclude in aop.xml) they really should only get aspectOf()/hasAspect()
  346. // and not be included in the full set of aspects being applied by 'this' weaver
  347. if (debugOn) {
  348. debug("weaving '" + name + "'");
  349. }
  350. newBytes = getWovenBytes(name, bytes);
  351. // TODO: Is this OK performance-wise?
  352. if (Arrays.equals(bytes, newBytes)) {
  353. // null means unchanged in java.lang.instrument.ClassFileTransformer::transform
  354. newBytes = null;
  355. }
  356. // temporarily out - searching for @Aspect annotated types is a slow thing to do - we should
  357. // expect the user to name them if they want them woven - just like code style
  358. // } else if (shouldWeaveAnnotationStyleAspect(name, bytes)) {
  359. // if (mustWeave) {
  360. // if (bcelWorld.getLint().mustWeaveXmlDefinedAspects.isEnabled()) {
  361. // bcelWorld.getLint().mustWeaveXmlDefinedAspects.signal(name, null);
  362. // }
  363. // }
  364. // // an @AspectJ aspect needs to be at least munged by the aspectOf munger
  365. // if (debugOn) {
  366. // debug("weaving '" + name + "'");
  367. // }
  368. // bytes = getAtAspectJAspectBytes(name, bytes);
  369. // Add the weaved class to the cache only if there
  370. // has been an actual change
  371. // JVK: Is there a better way to check if the class has
  372. // been transformed without carrying up some value
  373. // from the depths?
  374. if (cacheKey != null) {
  375. // If no transform has been applied, mark the class
  376. // as ignored.
  377. if (newBytes == null) {
  378. cache.ignore(cacheKey, bytes);
  379. } else {
  380. cache.put(cacheKey, bytes, newBytes);
  381. }
  382. }
  383. } else if (debugOn) {
  384. debug("not weaving '" + name + "'");
  385. }
  386. } else if (debugOn) {
  387. debug("cannot weave '" + name + "'");
  388. }
  389. } finally {
  390. delegateForCurrentClass = null;
  391. }
  392. if (trace.isTraceEnabled()) {
  393. trace.exit("weaveClass", newBytes);
  394. }
  395. return newBytes;
  396. } finally {
  397. weaverRunning.remove();
  398. }
  399. }
  400. /**
  401. * @param name
  402. * @return true if even valid to weave: either with an accept check or to munge it for @AspectJ aspectof support
  403. */
  404. private boolean couldWeave(String name, byte[] bytes) {
  405. return !generatedClasses.containsKey(name) && shouldWeaveName(name);
  406. }
  407. // ATAJ
  408. protected boolean accept(String name, byte[] bytes) {
  409. return true;
  410. }
  411. protected boolean shouldDump(String name, boolean before) {
  412. return false;
  413. }
  414. private boolean shouldWeaveName(String name) {
  415. if (PACKAGE_INITIAL_CHARS.indexOf(name.charAt(0)) != -1) {
  416. if ((weavingSpecialTypes & INITIALIZED) == 0) {
  417. weavingSpecialTypes |= INITIALIZED;
  418. // initialize it
  419. Properties p = weaver.getWorld().getExtraConfiguration();
  420. if (p != null) {
  421. boolean b = p.getProperty(World.xsetWEAVE_JAVA_PACKAGES, "false").equalsIgnoreCase("true");
  422. if (b) {
  423. weavingSpecialTypes |= WEAVE_JAVA_PACKAGE;
  424. }
  425. b = p.getProperty(World.xsetWEAVE_JAVAX_PACKAGES, "false").equalsIgnoreCase("true");
  426. if (b) {
  427. weavingSpecialTypes |= WEAVE_JAVAX_PACKAGE;
  428. }
  429. }
  430. }
  431. if (name.startsWith(ASPECTJ_BASE_PACKAGE)) {
  432. return false;
  433. }
  434. if (name.startsWith("sun.reflect.")) {// JDK reflect
  435. return false;
  436. }
  437. if (name.startsWith("javax.")) {
  438. if ((weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) != 0) {
  439. return true;
  440. } else {
  441. if (!haveWarnedOnJavax) {
  442. haveWarnedOnJavax = true;
  443. warn("javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified");
  444. }
  445. return false;
  446. }
  447. }
  448. if (name.startsWith("java.")) {
  449. if ((weavingSpecialTypes & WEAVE_JAVA_PACKAGE) != 0) {
  450. return true;
  451. } else {
  452. return false;
  453. }
  454. }
  455. }
  456. // boolean should = !(name.startsWith("org.aspectj.")
  457. // || (name.startsWith("java.") && (weavingSpecialTypes & WEAVE_JAVA_PACKAGE) == 0)
  458. // || (name.startsWith("javax.") && (weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) == 0)
  459. // // || name.startsWith("$Proxy")//JDK proxies//FIXME AV is that 1.3 proxy ? fe. ataspect.$Proxy0 is a java5 proxy...
  460. // || name.startsWith("sun.reflect."));
  461. return true;
  462. }
  463. /**
  464. * We allow @AJ aspect weaving so that we can add aspectOf() as part of the weaving (and not part of the source compilation)
  465. *
  466. * @param name
  467. * @param bytes bytecode (from classloader), allow to NOT lookup stuff on disk again during resolve
  468. * @return true if @Aspect
  469. */
  470. private boolean shouldWeaveAnnotationStyleAspect(String name, byte[] bytes) {
  471. if (delegateForCurrentClass == null) {
  472. // if (weaver.getWorld().isASMAround()) return asmCheckAnnotationStyleAspect(bytes);
  473. // else
  474. ensureDelegateInitialized(name, bytes);
  475. }
  476. return (delegateForCurrentClass.isAnnotationStyleAspect());
  477. }
  478. // private boolean asmCheckAnnotationStyleAspect(byte[] bytes) {
  479. // IsAtAspectAnnotationVisitor detector = new IsAtAspectAnnotationVisitor();
  480. //
  481. // ClassReader cr = new ClassReader(bytes);
  482. // try {
  483. // cr.accept(detector, true);//, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
  484. // } catch (Exception spe) {
  485. // // if anything goes wrong, e.g., an NPE, then assume it's NOT an @AspectJ aspect...
  486. // System.err.println("Unexpected problem parsing bytes to discover @Aspect annotation");
  487. // spe.printStackTrace();
  488. // return false;
  489. // }
  490. //
  491. // return detector.isAspect();
  492. // }
  493. protected void ensureDelegateInitialized(String name, byte[] bytes) {
  494. if (delegateForCurrentClass == null) {
  495. BcelWorld world = (BcelWorld) weaver.getWorld();
  496. delegateForCurrentClass = world.addSourceObjectType(name, bytes, false);
  497. }
  498. }
  499. /**
  500. * Weave a set of bytes defining a class.
  501. *
  502. * @param name the name of the class being woven
  503. * @param bytes the bytes that define the class
  504. * @return byte[] the woven bytes for the class
  505. * @throws IOException
  506. */
  507. private byte[] getWovenBytes(String name, byte[] bytes) throws IOException {
  508. WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
  509. weaver.weave(wcp);
  510. return wcp.getBytes();
  511. }
  512. /**
  513. * Weave a set of bytes defining a class for only what is needed to turn @AspectJ aspect in a usefull form ie with aspectOf
  514. * method - see #113587
  515. *
  516. * @param name the name of the class being woven
  517. * @param bytes the bytes that define the class
  518. * @return byte[] the woven bytes for the class
  519. * @throws IOException
  520. */
  521. private byte[] getAtAspectJAspectBytes(String name, byte[] bytes) throws IOException {
  522. WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
  523. wcp.setApplyAtAspectJMungersOnly();
  524. weaver.weave(wcp);
  525. return wcp.getBytes();
  526. }
  527. private void registerAspectLibraries(List<String> aspectPath) {
  528. // System.err.println("? WeavingAdaptor.registerAspectLibraries(" + aspectPath + ")");
  529. for (String libName : aspectPath) {
  530. addAspectLibrary(libName);
  531. }
  532. weaver.prepareForWeave();
  533. }
  534. /*
  535. * Register an aspect library with this classloader for use during weaving. This class loader will also return (unmodified) any
  536. * of the classes in the library in response to a <code>findClass()</code> request. The library is not required to be on the
  537. * weavingClasspath given when this classloader was constructed.
  538. *
  539. * @param aspectLibraryJarFile a jar file representing an aspect library
  540. *
  541. * @throws IOException
  542. */
  543. private void addAspectLibrary(String aspectLibraryName) {
  544. File aspectLibrary = new File(aspectLibraryName);
  545. if (aspectLibrary.isDirectory() || (FileUtil.isZipFile(aspectLibrary))) {
  546. try {
  547. info("adding aspect library: '" + aspectLibrary + "'");
  548. weaver.addLibraryJarFile(aspectLibrary);
  549. } catch (IOException ex) {
  550. error("exception adding aspect library: '" + ex + "'");
  551. }
  552. } else {
  553. error("bad aspect library: '" + aspectLibrary + "'");
  554. }
  555. }
  556. private static List<String> makeClasspath(String cp) {
  557. List<String> ret = new ArrayList<>();
  558. if (cp != null) {
  559. StringTokenizer tok = new StringTokenizer(cp, File.pathSeparator);
  560. while (tok.hasMoreTokens()) {
  561. ret.add(tok.nextToken());
  562. }
  563. }
  564. return ret;
  565. }
  566. protected boolean debug(String message) {
  567. return MessageUtil.debug(messageHandler, message);
  568. }
  569. protected boolean info(String message) {
  570. return MessageUtil.info(messageHandler, message);
  571. }
  572. protected boolean warn(String message) {
  573. return MessageUtil.warn(messageHandler, message);
  574. }
  575. protected boolean warn(String message, Throwable th) {
  576. return messageHandler.handleMessage(new Message(message, IMessage.WARNING, th, null));
  577. }
  578. protected boolean error(String message) {
  579. return MessageUtil.error(messageHandler, message);
  580. }
  581. protected boolean error(String message, Throwable th) {
  582. return messageHandler.handleMessage(new Message(message, IMessage.ERROR, th, null));
  583. }
  584. public String getContextId() {
  585. return "WeavingAdaptor";
  586. }
  587. /**
  588. * Dump the given bytcode in _dump/... (dev mode)
  589. *
  590. * @param name
  591. * @param b
  592. * @param before whether we are dumping before weaving
  593. */
  594. protected void dump(String name, byte[] b, boolean before) {
  595. String dirName = getDumpDir();
  596. if (before) {
  597. dirName = dirName + File.separator + "_before";
  598. }
  599. String className = name.replace('.', '/');
  600. final File dir;
  601. if (className.indexOf('/') > 0) {
  602. dir = new File(dirName + File.separator + className.substring(0, className.lastIndexOf('/')));
  603. } else {
  604. dir = new File(dirName);
  605. }
  606. dir.mkdirs();
  607. String fileName = dirName + File.separator + className + ".class";
  608. try {
  609. // System.out.println("WeavingAdaptor.dump() fileName=" + new File(fileName).getAbsolutePath());
  610. FileOutputStream os = new FileOutputStream(fileName);
  611. os.write(b);
  612. os.close();
  613. } catch (IOException ex) {
  614. warn("unable to dump class " + name + " in directory " + dirName, ex);
  615. }
  616. }
  617. /**
  618. * @return the directory in which to dump - default is _ajdump but it
  619. */
  620. protected String getDumpDir() {
  621. return "_ajdump";
  622. }
  623. /**
  624. * Processes messages arising from weaver operations. Tell weaver to abort on any message more severe than warning.
  625. */
  626. protected class WeavingAdaptorMessageHolder extends MessageHandler {
  627. private IMessageHandler delegate;
  628. private List<IMessage> savedMessages;
  629. protected boolean traceMessages = Boolean.getBoolean(TRACE_MESSAGES_PROPERTY);
  630. public WeavingAdaptorMessageHolder(PrintWriter writer) {
  631. this.delegate = new WeavingAdaptorMessageWriter(writer);
  632. super.dontIgnore(IMessage.WEAVEINFO);
  633. }
  634. private void traceMessage(IMessage message) {
  635. if (message instanceof WeaveMessage) {
  636. trace.debug(render(message));
  637. } else if (message.isDebug()) {
  638. trace.debug(render(message));
  639. } else if (message.isInfo()) {
  640. trace.info(render(message));
  641. } else if (message.isWarning()) {
  642. trace.warn(render(message), message.getThrown());
  643. } else if (message.isError()) {
  644. trace.error(render(message), message.getThrown());
  645. } else if (message.isFailed()) {
  646. trace.fatal(render(message), message.getThrown());
  647. } else if (message.isAbort()) {
  648. trace.fatal(render(message), message.getThrown());
  649. } else {
  650. trace.error(render(message), message.getThrown());
  651. }
  652. }
  653. protected String render(IMessage message) {
  654. return "[" + getContextId() + "] " + message.toString();
  655. }
  656. public void flushMessages() {
  657. if (savedMessages == null) {
  658. savedMessages = new ArrayList<>();
  659. savedMessages.addAll(super.getUnmodifiableListView());
  660. clearMessages();
  661. for (IMessage message : savedMessages) {
  662. delegate.handleMessage(message);
  663. }
  664. }
  665. // accumulating = false;
  666. // messages.clear();
  667. }
  668. public void setDelegate(IMessageHandler messageHandler) {
  669. delegate = messageHandler;
  670. }
  671. /*
  672. * IMessageHandler
  673. */
  674. @Override
  675. public boolean handleMessage(IMessage message) throws AbortException {
  676. if (traceMessages) {
  677. traceMessage(message);
  678. }
  679. super.handleMessage(message);
  680. if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
  681. throw new AbortException(message);
  682. }
  683. // if (accumulating) {
  684. // boolean result = addMessage(message);
  685. // if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
  686. // throw new AbortException(message);
  687. // }
  688. // return result;
  689. // }
  690. // else return delegate.handleMessage(message);
  691. if (savedMessages != null) {
  692. delegate.handleMessage(message);
  693. }
  694. return true;
  695. }
  696. @Override
  697. public boolean isIgnoring(Kind kind) {
  698. return delegate.isIgnoring(kind);
  699. }
  700. @Override
  701. public void dontIgnore(IMessage.Kind kind) {
  702. if (null != kind && delegate != null) {
  703. delegate.dontIgnore(kind);
  704. }
  705. }
  706. @Override
  707. public void ignore(Kind kind) {
  708. if (null != kind && delegate != null) {
  709. delegate.ignore(kind);
  710. }
  711. }
  712. /*
  713. * IMessageHolder
  714. */
  715. @Override
  716. public List<IMessage> getUnmodifiableListView() {
  717. // System.err.println("? WeavingAdaptorMessageHolder.getUnmodifiableListView() savedMessages=" + savedMessages);
  718. List<IMessage> allMessages = new ArrayList<>();
  719. allMessages.addAll(savedMessages);
  720. allMessages.addAll(super.getUnmodifiableListView());
  721. return allMessages;
  722. }
  723. }
  724. protected class WeavingAdaptorMessageWriter extends MessageWriter {
  725. private final Set<IMessage.Kind> ignoring = new HashSet<>();
  726. private final IMessage.Kind failKind;
  727. public WeavingAdaptorMessageWriter(PrintWriter writer) {
  728. super(writer, true);
  729. ignore(IMessage.WEAVEINFO);
  730. ignore(IMessage.DEBUG);
  731. ignore(IMessage.INFO);
  732. this.failKind = IMessage.ERROR;
  733. }
  734. @Override
  735. public boolean handleMessage(IMessage message) throws AbortException {
  736. // boolean result =
  737. super.handleMessage(message);
  738. if (abortOnError && 0 <= message.getKind().compareTo(failKind)) {
  739. throw new AbortException(message);
  740. }
  741. return true;
  742. }
  743. @Override
  744. public boolean isIgnoring(Kind kind) {
  745. return ((null != kind) && (ignoring.contains(kind)));
  746. }
  747. /**
  748. * Set a message kind to be ignored from now on
  749. */
  750. @Override
  751. public void ignore(IMessage.Kind kind) {
  752. if ((null != kind) && (!ignoring.contains(kind))) {
  753. ignoring.add(kind);
  754. }
  755. }
  756. /**
  757. * Remove a message kind from the list of those ignored from now on.
  758. */
  759. @Override
  760. public void dontIgnore(IMessage.Kind kind) {
  761. if (null != kind) {
  762. ignoring.remove(kind);
  763. }
  764. }
  765. @Override
  766. protected String render(IMessage message) {
  767. return "[" + getContextId() + "] " + super.render(message);
  768. }
  769. }
  770. private class WeavingClassFileProvider implements IClassFileProvider {
  771. private final UnwovenClassFile unwovenClass;
  772. private final List<UnwovenClassFile> unwovenClasses = new ArrayList<>();
  773. private IUnwovenClassFile wovenClass;
  774. private boolean isApplyAtAspectJMungersOnly = false;
  775. public WeavingClassFileProvider(String name, byte[] bytes) {
  776. ensureDelegateInitialized(name, bytes);
  777. this.unwovenClass = new UnwovenClassFile(name, delegateForCurrentClass.getResolvedTypeX().getName(), bytes);
  778. this.unwovenClasses.add(unwovenClass);
  779. if (shouldDump(name.replace('/', '.'), true)) {
  780. dump(name, bytes, true);
  781. }
  782. }
  783. public void setApplyAtAspectJMungersOnly() {
  784. isApplyAtAspectJMungersOnly = true;
  785. }
  786. public boolean isApplyAtAspectJMungersOnly() {
  787. return isApplyAtAspectJMungersOnly;
  788. }
  789. public byte[] getBytes() {
  790. if (wovenClass != null) {
  791. return wovenClass.getBytes();
  792. } else {
  793. return unwovenClass.getBytes();
  794. }
  795. }
  796. public Iterator<UnwovenClassFile> getClassFileIterator() {
  797. return unwovenClasses.iterator();
  798. }
  799. public IWeaveRequestor getRequestor() {
  800. return new IWeaveRequestor() {
  801. public void acceptResult(IUnwovenClassFile result) {
  802. if (wovenClass == null) {
  803. wovenClass = result;
  804. String name = result.getClassName();
  805. if (shouldDump(name.replace('/', '.'), false)) {
  806. dump(name, result.getBytes(), false);
  807. }
  808. } else {
  809. // Classes generated by weaver e.g. around closure advice
  810. String className = result.getClassName();
  811. byte[] resultBytes = result.getBytes();
  812. if (SimpleCacheFactory.isEnabled()) {
  813. SimpleCache lacache=SimpleCacheFactory.createSimpleCache();
  814. lacache.put(result.getClassName(), wovenClass.getBytes(), result.getBytes());
  815. lacache.addGeneratedClassesNames(wovenClass.getClassName(), wovenClass.getBytes(), result.getClassName());
  816. }
  817. generatedClasses.put(className, result);
  818. generatedClasses.put(wovenClass.getClassName(), wovenClass);
  819. generatedClassHandler.acceptClass(className, null, resultBytes);
  820. }
  821. }
  822. public void processingReweavableState() {
  823. }
  824. public void addingTypeMungers() {
  825. }
  826. public void weavingAspects() {
  827. }
  828. public void weavingClasses() {
  829. }
  830. public void weaveCompleted() {
  831. // ResolvedType.resetPrimitives();
  832. if (delegateForCurrentClass != null) {
  833. delegateForCurrentClass.weavingCompleted();
  834. }
  835. // ResolvedType.resetPrimitives();
  836. // bcelWorld.discardType(typeBeingProcessed.getResolvedTypeX()); // work in progress
  837. }
  838. };
  839. }
  840. }
  841. public void setActiveProtectionDomain(ProtectionDomain protectionDomain) {
  842. activeProtectionDomain = protectionDomain;
  843. }
  844. }