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 30KB

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
15 years ago
15 years ago
14 years ago
14 years ago
14 years ago
15 years ago
11 years ago
11 years ago
11 years ago
11 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
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  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 v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  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.is19VMOrGreater()) {
  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
  287. * @param bytes the class bytes
  288. * @param mustWeave if true then this class *must* get woven (used for concrete aspects generated from XML)
  289. * @return the woven bytes
  290. * @exception IOException weave failed
  291. */
  292. public byte[] weaveClass(String name, byte[] bytes, boolean mustWeave) throws IOException {
  293. if (trace == null) {
  294. // Pr231945: we are likely to be under tomcat and ENABLE_CLEAR_REFERENCES hasn't been set
  295. System.err
  296. .println("AspectJ Weaver cannot continue to weave, static state has been cleared. Are you under Tomcat? In order to weave '"
  297. + name
  298. + "' 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).");
  299. return bytes;
  300. }
  301. if (weaverRunning.get()) {
  302. // System.out.println("AJC: avoiding re-entrant call to transform " + name);
  303. return bytes;
  304. }
  305. try {
  306. weaverRunning.set(true);
  307. if (trace.isTraceEnabled()) {
  308. trace.enter("weaveClass", this, new Object[] { name, bytes });
  309. }
  310. if (!enabled) {
  311. if (trace.isTraceEnabled()) {
  312. trace.exit("weaveClass", false);
  313. }
  314. return bytes;
  315. }
  316. boolean debugOn = !messageHandler.isIgnoring(Message.DEBUG);
  317. try {
  318. delegateForCurrentClass = null;
  319. name = name.replace('/', '.');
  320. if (couldWeave(name, bytes)) {
  321. if (accept(name, bytes)) {
  322. // Determine if we have the weaved class cached
  323. CachedClassReference cacheKey = null;
  324. final byte[] original_bytes = bytes;
  325. if (cache != null && !mustWeave) {
  326. cacheKey = cache.createCacheKey(name, original_bytes);
  327. CachedClassEntry entry = cache.get(cacheKey, original_bytes);
  328. if (entry != null) {
  329. // If the entry has been explicitly ignored
  330. // return the original bytes
  331. if (entry.isIgnored()) {
  332. return bytes;
  333. }
  334. return entry.getBytes();
  335. }
  336. }
  337. // TODO @AspectJ problem
  338. // Annotation style aspects need to be included regardless in order to get
  339. // a valid aspectOf()/hasAspect() generated in them. However - if they are excluded
  340. // (via include/exclude in aop.xml) they really should only get aspectOf()/hasAspect()
  341. // and not be included in the full set of aspects being applied by 'this' weaver
  342. if (debugOn) {
  343. debug("weaving '" + name + "'");
  344. }
  345. bytes = getWovenBytes(name, bytes);
  346. // temporarily out - searching for @Aspect annotated types is a slow thing to do - we should
  347. // expect the user to name them if they want them woven - just like code style
  348. // } else if (shouldWeaveAnnotationStyleAspect(name, bytes)) {
  349. // if (mustWeave) {
  350. // if (bcelWorld.getLint().mustWeaveXmlDefinedAspects.isEnabled()) {
  351. // bcelWorld.getLint().mustWeaveXmlDefinedAspects.signal(name, null);
  352. // }
  353. // }
  354. // // an @AspectJ aspect needs to be at least munged by the aspectOf munger
  355. // if (debugOn) {
  356. // debug("weaving '" + name + "'");
  357. // }
  358. // bytes = getAtAspectJAspectBytes(name, bytes);
  359. // Add the weaved class to the cache only if there
  360. // has been an actual change
  361. // JVK: Is there a better way to check if the class has
  362. // been transformed without carrying up some value
  363. // from the depths?
  364. if (cacheKey != null) {
  365. // If no transform has been applied, mark the class
  366. // as ignored.
  367. if (Arrays.equals(original_bytes, bytes)) {
  368. cache.ignore(cacheKey, original_bytes);
  369. } else {
  370. cache.put(cacheKey, original_bytes, bytes);
  371. }
  372. }
  373. } else if (debugOn) {
  374. debug("not weaving '" + name + "'");
  375. }
  376. } else if (debugOn) {
  377. debug("cannot weave '" + name + "'");
  378. }
  379. } finally {
  380. delegateForCurrentClass = null;
  381. }
  382. if (trace.isTraceEnabled()) {
  383. trace.exit("weaveClass", bytes);
  384. }
  385. return bytes;
  386. } finally {
  387. weaverRunning.remove();
  388. }
  389. }
  390. /**
  391. * @param name
  392. * @return true if even valid to weave: either with an accept check or to munge it for @AspectJ aspectof support
  393. */
  394. private boolean couldWeave(String name, byte[] bytes) {
  395. return !generatedClasses.containsKey(name) && shouldWeaveName(name);
  396. }
  397. // ATAJ
  398. protected boolean accept(String name, byte[] bytes) {
  399. return true;
  400. }
  401. protected boolean shouldDump(String name, boolean before) {
  402. return false;
  403. }
  404. private boolean shouldWeaveName(String name) {
  405. if (PACKAGE_INITIAL_CHARS.indexOf(name.charAt(0)) != -1) {
  406. if ((weavingSpecialTypes & INITIALIZED) == 0) {
  407. weavingSpecialTypes |= INITIALIZED;
  408. // initialize it
  409. Properties p = weaver.getWorld().getExtraConfiguration();
  410. if (p != null) {
  411. boolean b = p.getProperty(World.xsetWEAVE_JAVA_PACKAGES, "false").equalsIgnoreCase("true");
  412. if (b) {
  413. weavingSpecialTypes |= WEAVE_JAVA_PACKAGE;
  414. }
  415. b = p.getProperty(World.xsetWEAVE_JAVAX_PACKAGES, "false").equalsIgnoreCase("true");
  416. if (b) {
  417. weavingSpecialTypes |= WEAVE_JAVAX_PACKAGE;
  418. }
  419. }
  420. }
  421. if (name.startsWith(ASPECTJ_BASE_PACKAGE)) {
  422. return false;
  423. }
  424. if (name.startsWith("sun.reflect.")) {// JDK reflect
  425. return false;
  426. }
  427. if (name.startsWith("javax.")) {
  428. if ((weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) != 0) {
  429. return true;
  430. } else {
  431. if (!haveWarnedOnJavax) {
  432. haveWarnedOnJavax = true;
  433. warn("javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified");
  434. }
  435. return false;
  436. }
  437. }
  438. if (name.startsWith("java.")) {
  439. if ((weavingSpecialTypes & WEAVE_JAVA_PACKAGE) != 0) {
  440. return true;
  441. } else {
  442. return false;
  443. }
  444. }
  445. }
  446. // boolean should = !(name.startsWith("org.aspectj.")
  447. // || (name.startsWith("java.") && (weavingSpecialTypes & WEAVE_JAVA_PACKAGE) == 0)
  448. // || (name.startsWith("javax.") && (weavingSpecialTypes & WEAVE_JAVAX_PACKAGE) == 0)
  449. // // || name.startsWith("$Proxy")//JDK proxies//FIXME AV is that 1.3 proxy ? fe. ataspect.$Proxy0 is a java5 proxy...
  450. // || name.startsWith("sun.reflect."));
  451. return true;
  452. }
  453. /**
  454. * We allow @AJ aspect weaving so that we can add aspectOf() as part of the weaving (and not part of the source compilation)
  455. *
  456. * @param name
  457. * @param bytes bytecode (from classloader), allow to NOT lookup stuff on disk again during resolve
  458. * @return true if @Aspect
  459. */
  460. private boolean shouldWeaveAnnotationStyleAspect(String name, byte[] bytes) {
  461. if (delegateForCurrentClass == null) {
  462. // if (weaver.getWorld().isASMAround()) return asmCheckAnnotationStyleAspect(bytes);
  463. // else
  464. ensureDelegateInitialized(name, bytes);
  465. }
  466. return (delegateForCurrentClass.isAnnotationStyleAspect());
  467. }
  468. // private boolean asmCheckAnnotationStyleAspect(byte[] bytes) {
  469. // IsAtAspectAnnotationVisitor detector = new IsAtAspectAnnotationVisitor();
  470. //
  471. // ClassReader cr = new ClassReader(bytes);
  472. // try {
  473. // cr.accept(detector, true);//, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
  474. // } catch (Exception spe) {
  475. // // if anything goes wrong, e.g., an NPE, then assume it's NOT an @AspectJ aspect...
  476. // System.err.println("Unexpected problem parsing bytes to discover @Aspect annotation");
  477. // spe.printStackTrace();
  478. // return false;
  479. // }
  480. //
  481. // return detector.isAspect();
  482. // }
  483. protected void ensureDelegateInitialized(String name, byte[] bytes) {
  484. if (delegateForCurrentClass == null) {
  485. BcelWorld world = (BcelWorld) weaver.getWorld();
  486. delegateForCurrentClass = world.addSourceObjectType(name, bytes, false);
  487. }
  488. }
  489. /**
  490. * Weave a set of bytes defining a class.
  491. *
  492. * @param name the name of the class being woven
  493. * @param bytes the bytes that define the class
  494. * @return byte[] the woven bytes for the class
  495. * @throws IOException
  496. */
  497. private byte[] getWovenBytes(String name, byte[] bytes) throws IOException {
  498. WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
  499. weaver.weave(wcp);
  500. return wcp.getBytes();
  501. }
  502. /**
  503. * Weave a set of bytes defining a class for only what is needed to turn @AspectJ aspect in a usefull form ie with aspectOf
  504. * method - see #113587
  505. *
  506. * @param name the name of the class being woven
  507. * @param bytes the bytes that define the class
  508. * @return byte[] the woven bytes for the class
  509. * @throws IOException
  510. */
  511. private byte[] getAtAspectJAspectBytes(String name, byte[] bytes) throws IOException {
  512. WeavingClassFileProvider wcp = new WeavingClassFileProvider(name, bytes);
  513. wcp.setApplyAtAspectJMungersOnly();
  514. weaver.weave(wcp);
  515. return wcp.getBytes();
  516. }
  517. private void registerAspectLibraries(List aspectPath) {
  518. // System.err.println("? WeavingAdaptor.registerAspectLibraries(" + aspectPath + ")");
  519. for (Object o : aspectPath) {
  520. String libName = (String) o;
  521. addAspectLibrary(libName);
  522. }
  523. weaver.prepareForWeave();
  524. }
  525. /*
  526. * Register an aspect library with this classloader for use during weaving. This class loader will also return (unmodified) any
  527. * of the classes in the library in response to a <code>findClass()</code> request. The library is not required to be on the
  528. * weavingClasspath given when this classloader was constructed.
  529. *
  530. * @param aspectLibraryJarFile a jar file representing an aspect library
  531. *
  532. * @throws IOException
  533. */
  534. private void addAspectLibrary(String aspectLibraryName) {
  535. File aspectLibrary = new File(aspectLibraryName);
  536. if (aspectLibrary.isDirectory() || (FileUtil.isZipFile(aspectLibrary))) {
  537. try {
  538. info("adding aspect library: '" + aspectLibrary + "'");
  539. weaver.addLibraryJarFile(aspectLibrary);
  540. } catch (IOException ex) {
  541. error("exception adding aspect library: '" + ex + "'");
  542. }
  543. } else {
  544. error("bad aspect library: '" + aspectLibrary + "'");
  545. }
  546. }
  547. private static List<String> makeClasspath(String cp) {
  548. List<String> ret = new ArrayList<>();
  549. if (cp != null) {
  550. StringTokenizer tok = new StringTokenizer(cp, File.pathSeparator);
  551. while (tok.hasMoreTokens()) {
  552. ret.add(tok.nextToken());
  553. }
  554. }
  555. return ret;
  556. }
  557. protected boolean debug(String message) {
  558. return MessageUtil.debug(messageHandler, message);
  559. }
  560. protected boolean info(String message) {
  561. return MessageUtil.info(messageHandler, message);
  562. }
  563. protected boolean warn(String message) {
  564. return MessageUtil.warn(messageHandler, message);
  565. }
  566. protected boolean warn(String message, Throwable th) {
  567. return messageHandler.handleMessage(new Message(message, IMessage.WARNING, th, null));
  568. }
  569. protected boolean error(String message) {
  570. return MessageUtil.error(messageHandler, message);
  571. }
  572. protected boolean error(String message, Throwable th) {
  573. return messageHandler.handleMessage(new Message(message, IMessage.ERROR, th, null));
  574. }
  575. public String getContextId() {
  576. return "WeavingAdaptor";
  577. }
  578. /**
  579. * Dump the given bytcode in _dump/... (dev mode)
  580. *
  581. * @param name
  582. * @param b
  583. * @param before whether we are dumping before weaving
  584. */
  585. protected void dump(String name, byte[] b, boolean before) {
  586. String dirName = getDumpDir();
  587. if (before) {
  588. dirName = dirName + File.separator + "_before";
  589. }
  590. String className = name.replace('.', '/');
  591. final File dir;
  592. if (className.indexOf('/') > 0) {
  593. dir = new File(dirName + File.separator + className.substring(0, className.lastIndexOf('/')));
  594. } else {
  595. dir = new File(dirName);
  596. }
  597. dir.mkdirs();
  598. String fileName = dirName + File.separator + className + ".class";
  599. try {
  600. // System.out.println("WeavingAdaptor.dump() fileName=" + new File(fileName).getAbsolutePath());
  601. FileOutputStream os = new FileOutputStream(fileName);
  602. os.write(b);
  603. os.close();
  604. } catch (IOException ex) {
  605. warn("unable to dump class " + name + " in directory " + dirName, ex);
  606. }
  607. }
  608. /**
  609. * @return the directory in which to dump - default is _ajdump but it
  610. */
  611. protected String getDumpDir() {
  612. return "_ajdump";
  613. }
  614. /**
  615. * Processes messages arising from weaver operations. Tell weaver to abort on any message more severe than warning.
  616. */
  617. protected class WeavingAdaptorMessageHolder extends MessageHandler {
  618. private IMessageHandler delegate;
  619. private List<IMessage> savedMessages;
  620. protected boolean traceMessages = Boolean.getBoolean(TRACE_MESSAGES_PROPERTY);
  621. public WeavingAdaptorMessageHolder(PrintWriter writer) {
  622. this.delegate = new WeavingAdaptorMessageWriter(writer);
  623. super.dontIgnore(IMessage.WEAVEINFO);
  624. }
  625. private void traceMessage(IMessage message) {
  626. if (message instanceof WeaveMessage) {
  627. trace.debug(render(message));
  628. } else if (message.isDebug()) {
  629. trace.debug(render(message));
  630. } else if (message.isInfo()) {
  631. trace.info(render(message));
  632. } else if (message.isWarning()) {
  633. trace.warn(render(message), message.getThrown());
  634. } else if (message.isError()) {
  635. trace.error(render(message), message.getThrown());
  636. } else if (message.isFailed()) {
  637. trace.fatal(render(message), message.getThrown());
  638. } else if (message.isAbort()) {
  639. trace.fatal(render(message), message.getThrown());
  640. } else {
  641. trace.error(render(message), message.getThrown());
  642. }
  643. }
  644. protected String render(IMessage message) {
  645. return "[" + getContextId() + "] " + message.toString();
  646. }
  647. public void flushMessages() {
  648. if (savedMessages == null) {
  649. savedMessages = new ArrayList<>();
  650. savedMessages.addAll(super.getUnmodifiableListView());
  651. clearMessages();
  652. for (IMessage message : savedMessages) {
  653. delegate.handleMessage(message);
  654. }
  655. }
  656. // accumulating = false;
  657. // messages.clear();
  658. }
  659. public void setDelegate(IMessageHandler messageHandler) {
  660. delegate = messageHandler;
  661. }
  662. /*
  663. * IMessageHandler
  664. */
  665. @Override
  666. public boolean handleMessage(IMessage message) throws AbortException {
  667. if (traceMessages) {
  668. traceMessage(message);
  669. }
  670. super.handleMessage(message);
  671. if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
  672. throw new AbortException(message);
  673. }
  674. // if (accumulating) {
  675. // boolean result = addMessage(message);
  676. // if (abortOnError && 0 <= message.getKind().compareTo(IMessage.ERROR)) {
  677. // throw new AbortException(message);
  678. // }
  679. // return result;
  680. // }
  681. // else return delegate.handleMessage(message);
  682. if (savedMessages != null) {
  683. delegate.handleMessage(message);
  684. }
  685. return true;
  686. }
  687. @Override
  688. public boolean isIgnoring(Kind kind) {
  689. return delegate.isIgnoring(kind);
  690. }
  691. @Override
  692. public void dontIgnore(IMessage.Kind kind) {
  693. if (null != kind && delegate != null) {
  694. delegate.dontIgnore(kind);
  695. }
  696. }
  697. @Override
  698. public void ignore(Kind kind) {
  699. if (null != kind && delegate != null) {
  700. delegate.ignore(kind);
  701. }
  702. }
  703. /*
  704. * IMessageHolder
  705. */
  706. @Override
  707. public List<IMessage> getUnmodifiableListView() {
  708. // System.err.println("? WeavingAdaptorMessageHolder.getUnmodifiableListView() savedMessages=" + savedMessages);
  709. List<IMessage> allMessages = new ArrayList<>();
  710. allMessages.addAll(savedMessages);
  711. allMessages.addAll(super.getUnmodifiableListView());
  712. return allMessages;
  713. }
  714. }
  715. protected class WeavingAdaptorMessageWriter extends MessageWriter {
  716. private final Set<IMessage.Kind> ignoring = new HashSet<>();
  717. private final IMessage.Kind failKind;
  718. public WeavingAdaptorMessageWriter(PrintWriter writer) {
  719. super(writer, true);
  720. ignore(IMessage.WEAVEINFO);
  721. ignore(IMessage.DEBUG);
  722. ignore(IMessage.INFO);
  723. this.failKind = IMessage.ERROR;
  724. }
  725. @Override
  726. public boolean handleMessage(IMessage message) throws AbortException {
  727. // boolean result =
  728. super.handleMessage(message);
  729. if (abortOnError && 0 <= message.getKind().compareTo(failKind)) {
  730. throw new AbortException(message);
  731. }
  732. return true;
  733. }
  734. @Override
  735. public boolean isIgnoring(Kind kind) {
  736. return ((null != kind) && (ignoring.contains(kind)));
  737. }
  738. /**
  739. * Set a message kind to be ignored from now on
  740. */
  741. @Override
  742. public void ignore(IMessage.Kind kind) {
  743. if ((null != kind) && (!ignoring.contains(kind))) {
  744. ignoring.add(kind);
  745. }
  746. }
  747. /**
  748. * Remove a message kind from the list of those ignored from now on.
  749. */
  750. @Override
  751. public void dontIgnore(IMessage.Kind kind) {
  752. if (null != kind) {
  753. ignoring.remove(kind);
  754. }
  755. }
  756. @Override
  757. protected String render(IMessage message) {
  758. return "[" + getContextId() + "] " + super.render(message);
  759. }
  760. }
  761. private class WeavingClassFileProvider implements IClassFileProvider {
  762. private final UnwovenClassFile unwovenClass;
  763. private final List<UnwovenClassFile> unwovenClasses = new ArrayList<>();
  764. private IUnwovenClassFile wovenClass;
  765. private boolean isApplyAtAspectJMungersOnly = false;
  766. public WeavingClassFileProvider(String name, byte[] bytes) {
  767. ensureDelegateInitialized(name, bytes);
  768. this.unwovenClass = new UnwovenClassFile(name, delegateForCurrentClass.getResolvedTypeX().getName(), bytes);
  769. this.unwovenClasses.add(unwovenClass);
  770. if (shouldDump(name.replace('/', '.'), true)) {
  771. dump(name, bytes, true);
  772. }
  773. }
  774. public void setApplyAtAspectJMungersOnly() {
  775. isApplyAtAspectJMungersOnly = true;
  776. }
  777. public boolean isApplyAtAspectJMungersOnly() {
  778. return isApplyAtAspectJMungersOnly;
  779. }
  780. public byte[] getBytes() {
  781. if (wovenClass != null) {
  782. return wovenClass.getBytes();
  783. } else {
  784. return unwovenClass.getBytes();
  785. }
  786. }
  787. public Iterator<UnwovenClassFile> getClassFileIterator() {
  788. return unwovenClasses.iterator();
  789. }
  790. public IWeaveRequestor getRequestor() {
  791. return new IWeaveRequestor() {
  792. public void acceptResult(IUnwovenClassFile result) {
  793. if (wovenClass == null) {
  794. wovenClass = result;
  795. String name = result.getClassName();
  796. if (shouldDump(name.replace('/', '.'), false)) {
  797. dump(name, result.getBytes(), false);
  798. }
  799. } else {
  800. // Classes generated by weaver e.g. around closure advice
  801. String className = result.getClassName();
  802. byte[] resultBytes = result.getBytes();
  803. if (SimpleCacheFactory.isEnabled()) {
  804. SimpleCache lacache=SimpleCacheFactory.createSimpleCache();
  805. lacache.put(result.getClassName(), wovenClass.getBytes(), result.getBytes());
  806. lacache.addGeneratedClassesNames(wovenClass.getClassName(), wovenClass.getBytes(), result.getClassName());
  807. }
  808. generatedClasses.put(className, result);
  809. generatedClasses.put(wovenClass.getClassName(), result);
  810. generatedClassHandler.acceptClass(className, null, resultBytes);
  811. }
  812. }
  813. public void processingReweavableState() {
  814. }
  815. public void addingTypeMungers() {
  816. }
  817. public void weavingAspects() {
  818. }
  819. public void weavingClasses() {
  820. }
  821. public void weaveCompleted() {
  822. // ResolvedType.resetPrimitives();
  823. if (delegateForCurrentClass != null) {
  824. delegateForCurrentClass.weavingCompleted();
  825. }
  826. // ResolvedType.resetPrimitives();
  827. // bcelWorld.discardType(typeBeingProcessed.getResolvedTypeX()); // work in progress
  828. }
  829. };
  830. }
  831. }
  832. public void setActiveProtectionDomain(ProtectionDomain protectionDomain) {
  833. activeProtectionDomain = protectionDomain;
  834. }
  835. }