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.

ClassLoaderWeavingAdaptor.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*******************************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Alexandre Vasseur initial implementation
  11. * David Knibb weaving context enhancments
  12. *******************************************************************************/
  13. package org.aspectj.weaver.loadtime;
  14. import java.io.File;
  15. import java.io.IOException;
  16. import java.io.InputStream;
  17. import java.lang.reflect.InvocationTargetException;
  18. import java.lang.reflect.Method;
  19. import java.net.URL;
  20. import java.util.ArrayList;
  21. import java.util.Enumeration;
  22. import java.util.HashMap;
  23. import java.util.HashSet;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Properties;
  27. import java.util.Set;
  28. import java.util.StringTokenizer;
  29. import org.aspectj.asm.IRelationship;
  30. import org.aspectj.bridge.AbortException;
  31. import org.aspectj.bridge.Constants;
  32. import org.aspectj.bridge.ISourceLocation;
  33. import org.aspectj.util.LangUtil;
  34. import org.aspectj.weaver.ICrossReferenceHandler;
  35. import org.aspectj.weaver.Lint;
  36. import org.aspectj.weaver.ResolvedType;
  37. import org.aspectj.weaver.UnresolvedType;
  38. import org.aspectj.weaver.World;
  39. import org.aspectj.weaver.Lint.Kind;
  40. import org.aspectj.weaver.bcel.BcelWeaver;
  41. import org.aspectj.weaver.bcel.BcelWorld;
  42. import org.aspectj.weaver.bcel.Utility;
  43. import org.aspectj.weaver.loadtime.definition.Definition;
  44. import org.aspectj.weaver.loadtime.definition.DocumentParser;
  45. import org.aspectj.weaver.ltw.LTWWorld;
  46. import org.aspectj.weaver.patterns.PatternParser;
  47. import org.aspectj.weaver.patterns.TypePattern;
  48. import org.aspectj.weaver.tools.GeneratedClassHandler;
  49. import org.aspectj.weaver.tools.Trace;
  50. import org.aspectj.weaver.tools.TraceFactory;
  51. import org.aspectj.weaver.tools.WeavingAdaptor;
  52. /**
  53. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  54. */
  55. public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
  56. private final static String AOP_XML = Constants.AOP_USER_XML + ";" + Constants.AOP_AJC_XML + ";" + Constants.AOP_OSGI_XML;
  57. private boolean initialized;
  58. private List m_dumpTypePattern = new ArrayList();
  59. private boolean m_dumpBefore = false;
  60. private List m_includeTypePattern = new ArrayList();
  61. private List m_excludeTypePattern = new ArrayList();
  62. private List m_includeStartsWith = new ArrayList();
  63. private List m_excludeStartsWith = new ArrayList();
  64. private List m_aspectExcludeTypePattern = new ArrayList();
  65. private List m_aspectExcludeStartsWith = new ArrayList();
  66. private List m_aspectIncludeTypePattern = new ArrayList();
  67. private List m_aspectIncludeStartsWith = new ArrayList();
  68. private StringBuffer namespace;
  69. private IWeavingContext weavingContext;
  70. private List concreteAspects = new ArrayList();
  71. private static Trace trace = TraceFactory.getTraceFactory().getTrace(ClassLoaderWeavingAdaptor.class);
  72. public ClassLoaderWeavingAdaptor() {
  73. super();
  74. if (trace.isTraceEnabled()) trace.enter("<init>",this);
  75. if (trace.isTraceEnabled()) trace.exit("<init>");
  76. }
  77. /**
  78. * We don't need a reference to the class loader and using it during
  79. * construction can cause problems with recursion. It also makes sense
  80. * to supply the weaving context during initialization to.
  81. * @deprecated
  82. */
  83. public ClassLoaderWeavingAdaptor(final ClassLoader deprecatedLoader, final IWeavingContext deprecatedContext) {
  84. super();
  85. if (trace.isTraceEnabled()) trace.enter("<init>",this,new Object[] { deprecatedLoader, deprecatedContext });
  86. if (trace.isTraceEnabled()) trace.exit("<init>");
  87. }
  88. protected void initialize (final ClassLoader classLoader, IWeavingContext context) {
  89. if (initialized) return;
  90. boolean success = true;
  91. if (trace.isTraceEnabled()) trace.enter("initialize",this,new Object[] { classLoader, context });
  92. this.weavingContext = context;
  93. if (weavingContext == null) {
  94. weavingContext = new DefaultWeavingContext(classLoader);
  95. }
  96. createMessageHandler();
  97. this.generatedClassHandler = new GeneratedClassHandler() {
  98. /**
  99. * Callback when we need to define a Closure in the JVM
  100. *
  101. * @param name
  102. * @param bytes
  103. */
  104. public void acceptClass(String name, byte[] bytes) {
  105. try {
  106. if (shouldDump(name.replace('/', '.'), false)) {
  107. dump(name, bytes, false);
  108. }
  109. } catch (Throwable throwable) {
  110. throwable.printStackTrace();
  111. }
  112. defineClass(classLoader, name, bytes);// could be done lazily using the hook
  113. }
  114. };
  115. List definitions = parseDefinitions(classLoader);
  116. if (definitions.isEmpty()) {
  117. disable(); // TODO maw Needed to ensure messages are flushed
  118. if (trace.isTraceEnabled()) trace.exit("initialize",definitions);
  119. return;
  120. }
  121. bcelWorld = new LTWWorld(
  122. classLoader, weavingContext, // TODO when the world works in terms of the context, we can remove the loader...
  123. getMessageHandler(), new ICrossReferenceHandler() {
  124. public void addCrossReference(ISourceLocation from, ISourceLocation to, IRelationship.Kind kind, boolean runtimeTest) {
  125. ;// for tools only
  126. }
  127. }
  128. );
  129. weaver = new BcelWeaver(bcelWorld);
  130. // register the definitions
  131. success = registerDefinitions(weaver, classLoader, definitions);
  132. if (success) {
  133. // after adding aspects
  134. weaver.prepareForWeave();
  135. enable(); // TODO maw Needed to ensure messages are flushed
  136. success = weaveAndDefineConceteAspects();
  137. }
  138. if (success) {
  139. enable();
  140. }
  141. else {
  142. disable();
  143. bcelWorld = null;
  144. weaver = null;
  145. }
  146. initialized = true;
  147. if (trace.isTraceEnabled()) trace.exit("initialize",isEnabled());
  148. }
  149. /**
  150. * Load and cache the aop.xml/properties according to the classloader visibility rules
  151. *
  152. * @param weaver
  153. * @param loader
  154. */
  155. private List parseDefinitions(final ClassLoader loader) {
  156. if (trace.isTraceEnabled()) trace.enter("parseDefinitions",this,loader);
  157. List definitions = new ArrayList();
  158. try {
  159. info("register classloader " + getClassLoaderName(loader));
  160. //TODO av underoptimized: we will parse each XML once per CL that see it
  161. //TODO av dev mode needed ? TBD -Daj5.def=...
  162. if (loader.equals(ClassLoader.getSystemClassLoader())) {
  163. String file = System.getProperty("aj5.def", null);
  164. if (file != null) {
  165. info("using (-Daj5.def) " + file);
  166. definitions.add(DocumentParser.parse((new File(file)).toURL()));
  167. }
  168. }
  169. String resourcePath = System.getProperty("org.aspectj.weaver.loadtime.configuration",AOP_XML);
  170. if (trace.isTraceEnabled()) trace.event("parseDefinitions",this,resourcePath);
  171. StringTokenizer st = new StringTokenizer(resourcePath,";");
  172. while(st.hasMoreTokens()){
  173. Enumeration xmls = weavingContext.getResources(st.nextToken());
  174. // System.out.println("? registerDefinitions: found-aop.xml=" + xmls.hasMoreElements() + ", loader=" + loader);
  175. Set seenBefore = new HashSet();
  176. while (xmls.hasMoreElements()) {
  177. URL xml = (URL) xmls.nextElement();
  178. if (trace.isTraceEnabled()) trace.event("parseDefinitions",this,xml);
  179. if (!seenBefore.contains(xml)) {
  180. info("using configuration " + weavingContext.getFile(xml));
  181. definitions.add(DocumentParser.parse(xml));
  182. seenBefore.add(xml);
  183. }
  184. else {
  185. warn("ignoring duplicate definition: " + xml);
  186. }
  187. }
  188. }
  189. if (definitions.isEmpty()) {
  190. info("no configuration found. Disabling weaver for class loader " + getClassLoaderName(loader));
  191. }
  192. } catch (Exception e) {
  193. definitions.clear();
  194. warn("parse definitions failed",e);
  195. }
  196. if (trace.isTraceEnabled()) trace.exit("parseDefinitions",definitions);
  197. return definitions;
  198. }
  199. private boolean registerDefinitions(final BcelWeaver weaver, final ClassLoader loader, List definitions) {
  200. if (trace.isTraceEnabled()) trace.enter("registerDefinitions",this,definitions);
  201. boolean success = true;
  202. try {
  203. registerOptions(weaver, loader, definitions);
  204. registerAspectExclude(weaver, loader, definitions);
  205. registerAspectInclude(weaver, loader, definitions);
  206. success = registerAspects(weaver, loader, definitions);
  207. registerIncludeExclude(weaver, loader, definitions);
  208. registerDump(weaver, loader, definitions);
  209. } catch (Exception ex) {
  210. trace.error("register definition failed",ex);
  211. success = false;
  212. warn("register definition failed",(ex instanceof AbortException)?null:ex);
  213. }
  214. if (trace.isTraceEnabled()) trace.exit("registerDefinitions",success);
  215. return success;
  216. }
  217. private String getClassLoaderName (ClassLoader loader) {
  218. return weavingContext.getClassLoaderName();
  219. }
  220. /**
  221. * Configure the weaver according to the option directives
  222. * TODO av - don't know if it is that good to reuse, since we only allow a small subset of options in LTW
  223. *
  224. * @param weaver
  225. * @param loader
  226. * @param definitions
  227. */
  228. private void registerOptions(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  229. StringBuffer allOptions = new StringBuffer();
  230. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  231. Definition definition = (Definition) iterator.next();
  232. allOptions.append(definition.getWeaverOptions()).append(' ');
  233. }
  234. Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader, getMessageHandler());
  235. // configure the weaver and world
  236. // AV - code duplicates AspectJBuilder.initWorldAndWeaver()
  237. World world = weaver.getWorld();
  238. setMessageHandler(weaverOption.messageHandler);
  239. world.setXlazyTjp(weaverOption.lazyTjp);
  240. world.setXHasMemberSupportEnabled(weaverOption.hasMember);
  241. world.setOptionalJoinpoints(weaverOption.optionalJoinpoints);
  242. world.setPinpointMode(weaverOption.pinpoint);
  243. weaver.setReweavableMode(weaverOption.notReWeavable);
  244. world.performExtraConfiguration(weaverOption.xSet);
  245. world.setXnoInline(weaverOption.noInline);
  246. // AMC - autodetect as per line below, needed for AtAjLTWTests.testLTWUnweavable
  247. world.setBehaveInJava5Way(LangUtil.is15VMOrGreater());
  248. world.setAddSerialVerUID(weaverOption.addSerialVersionUID);
  249. /* First load defaults */
  250. bcelWorld.getLint().loadDefaultProperties();
  251. /* Second overlay LTW defaults */
  252. bcelWorld.getLint().adviceDidNotMatch.setKind(null);
  253. /* Third load user file using -Xlintfile so that -Xlint wins */
  254. if (weaverOption.lintFile != null) {
  255. InputStream resource = null;
  256. try {
  257. resource = loader.getResourceAsStream(weaverOption.lintFile);
  258. Exception failure = null;
  259. if (resource != null) {
  260. try {
  261. Properties properties = new Properties();
  262. properties.load(resource);
  263. world.getLint().setFromProperties(properties);
  264. } catch (IOException e) {
  265. failure = e;
  266. }
  267. }
  268. if (failure != null || resource == null) {
  269. warn("Cannot access resource for -Xlintfile:"+weaverOption.lintFile,failure);
  270. // world.getMessageHandler().handleMessage(new Message(
  271. // "Cannot access resource for -Xlintfile:"+weaverOption.lintFile,
  272. // IMessage.WARNING,
  273. // failure,
  274. // null));
  275. }
  276. } finally {
  277. try { resource.close(); } catch (Throwable t) {;}
  278. }
  279. }
  280. /* Fourth override with -Xlint */
  281. if (weaverOption.lint != null) {
  282. if (weaverOption.lint.equals("default")) {//FIXME should be AjBuildConfig.AJLINT_DEFAULT but yetanother deps..
  283. bcelWorld.getLint().loadDefaultProperties();
  284. } else {
  285. bcelWorld.getLint().setAll(weaverOption.lint);
  286. }
  287. }
  288. //TODO proceedOnError option
  289. }
  290. private void registerAspectExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  291. String fastMatchInfo = null;
  292. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  293. Definition definition = (Definition) iterator.next();
  294. for (Iterator iterator1 = definition.getAspectExcludePatterns().iterator(); iterator1.hasNext();) {
  295. String exclude = (String) iterator1.next();
  296. TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
  297. m_aspectExcludeTypePattern.add(excludePattern);
  298. fastMatchInfo = looksLikeStartsWith(exclude);
  299. if (fastMatchInfo != null) {
  300. m_aspectExcludeStartsWith.add(fastMatchInfo);
  301. }
  302. }
  303. }
  304. }
  305. private void registerAspectInclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  306. String fastMatchInfo = null;
  307. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  308. Definition definition = (Definition) iterator.next();
  309. for (Iterator iterator1 = definition.getAspectIncludePatterns().iterator(); iterator1.hasNext();) {
  310. String include = (String) iterator1.next();
  311. TypePattern includePattern = new PatternParser(include).parseTypePattern();
  312. m_aspectIncludeTypePattern.add(includePattern);
  313. fastMatchInfo = looksLikeStartsWith(include);
  314. if (fastMatchInfo != null) {
  315. m_aspectIncludeStartsWith.add(fastMatchInfo);
  316. }
  317. }
  318. }
  319. }
  320. protected void lint (String name, String[] infos) {
  321. Lint lint = bcelWorld.getLint();
  322. Kind kind = lint.getLintKind(name);
  323. kind.signal(infos,null,null);
  324. }
  325. public String getContextId () {
  326. return weavingContext.getId();
  327. }
  328. /**
  329. * Register the aspect, following include / exclude rules
  330. *
  331. * @param weaver
  332. * @param loader
  333. * @param definitions
  334. */
  335. private boolean registerAspects(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  336. if (trace.isTraceEnabled()) trace.enter("registerAspects",this, new Object[] { weaver, loader, definitions} );
  337. boolean success = true;
  338. //TODO: the exclude aspect allow to exclude aspect defined upper in the CL hierarchy - is it what we want ??
  339. // if not, review the getResource so that we track which resource is defined by which CL
  340. //iterate aspectClassNames
  341. //exclude if in any of the exclude list
  342. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  343. Definition definition = (Definition) iterator.next();
  344. for (Iterator aspects = definition.getAspectClassNames().iterator(); aspects.hasNext();) {
  345. String aspectClassName = (String) aspects.next();
  346. if (acceptAspect(aspectClassName)) {
  347. info("register aspect " + aspectClassName);
  348. // System.err.println("? ClassLoaderWeavingAdaptor.registerAspects() aspectName=" + aspectClassName + ", loader=" + loader + ", bundle=" + weavingContext.getClassLoaderName());
  349. /*ResolvedType aspect = */weaver.addLibraryAspect(aspectClassName);
  350. //generate key for SC
  351. if(namespace==null){
  352. namespace=new StringBuffer(aspectClassName);
  353. }else{
  354. namespace = namespace.append(";"+aspectClassName);
  355. }
  356. }
  357. else {
  358. // warn("aspect excluded: " + aspectClassName);
  359. lint("aspectExcludedByConfiguration", new String[] { aspectClassName, getClassLoaderName(loader) });
  360. }
  361. }
  362. }
  363. //iterate concreteAspects
  364. //exclude if in any of the exclude list - note that the user defined name matters for that to happen
  365. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  366. Definition definition = (Definition) iterator.next();
  367. for (Iterator aspects = definition.getConcreteAspects().iterator(); aspects.hasNext();) {
  368. Definition.ConcreteAspect concreteAspect = (Definition.ConcreteAspect) aspects.next();
  369. if (acceptAspect(concreteAspect.name)) {
  370. info("define aspect " + concreteAspect.name);
  371. ConcreteAspectCodeGen gen = new ConcreteAspectCodeGen(concreteAspect, weaver.getWorld());
  372. if (!gen.validate()) {
  373. error("Concrete-aspect '"+concreteAspect.name+"' could not be registered");
  374. success = false;
  375. break;
  376. }
  377. ((BcelWorld)weaver.getWorld()).addSourceObjectType(Utility.makeJavaClass(concreteAspect.name, gen.getBytes()));
  378. concreteAspects.add(gen);
  379. weaver.addLibraryAspect(concreteAspect.name);
  380. //generate key for SC
  381. if(namespace==null){
  382. namespace=new StringBuffer(concreteAspect.name);
  383. }else{
  384. namespace = namespace.append(";"+concreteAspect.name);
  385. }
  386. }
  387. }
  388. }
  389. /* We couldn't register one or more aspects so disable the adaptor */
  390. if (!success) {
  391. warn("failure(s) registering aspects. Disabling weaver for class loader " + getClassLoaderName(loader));
  392. }
  393. /* We didn't register any aspects so disable the adaptor */
  394. else if (namespace == null) {
  395. success = false;
  396. info("no aspects registered. Disabling weaver for class loader " + getClassLoaderName(loader));
  397. }
  398. if (trace.isTraceEnabled()) trace.exit("registerAspects",success);
  399. return success;
  400. }
  401. private boolean weaveAndDefineConceteAspects () {
  402. if (trace.isTraceEnabled()) trace.enter("weaveAndDefineConceteAspects",this,concreteAspects);
  403. boolean success = true;
  404. for (Iterator iterator = concreteAspects.iterator(); iterator.hasNext();) {
  405. ConcreteAspectCodeGen gen = (ConcreteAspectCodeGen)iterator.next();
  406. String name = gen.getClassName();
  407. byte[] bytes = gen.getBytes();
  408. try {
  409. byte[] newBytes = weaveClass(name, bytes);
  410. this.generatedClassHandler.acceptClass(name,newBytes);
  411. }
  412. catch (IOException ex) {
  413. trace.error("weaveAndDefineConceteAspects",ex);
  414. error("exception weaving aspect '" + name + "'",ex);
  415. }
  416. }
  417. if (trace.isTraceEnabled()) trace.exit("weaveAndDefineConceteAspects",success);
  418. return success;
  419. }
  420. /**
  421. * Register the include / exclude filters
  422. * We duplicate simple patterns in startWith filters that will allow faster matching without ResolvedType
  423. *
  424. * @param weaver
  425. * @param loader
  426. * @param definitions
  427. */
  428. private void registerIncludeExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  429. String fastMatchInfo = null;
  430. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  431. Definition definition = (Definition) iterator.next();
  432. for (Iterator iterator1 = definition.getIncludePatterns().iterator(); iterator1.hasNext();) {
  433. String include = (String) iterator1.next();
  434. TypePattern includePattern = new PatternParser(include).parseTypePattern();
  435. m_includeTypePattern.add(includePattern);
  436. fastMatchInfo = looksLikeStartsWith(include);
  437. if (fastMatchInfo != null) {
  438. m_includeStartsWith.add(fastMatchInfo);
  439. }
  440. }
  441. for (Iterator iterator1 = definition.getExcludePatterns().iterator(); iterator1.hasNext();) {
  442. String exclude = (String) iterator1.next();
  443. TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
  444. m_excludeTypePattern.add(excludePattern);
  445. fastMatchInfo = looksLikeStartsWith(exclude);
  446. if (fastMatchInfo != null) {
  447. m_excludeStartsWith.add(fastMatchInfo);
  448. }
  449. }
  450. }
  451. }
  452. /**
  453. * Checks if the type pattern can be handled as a startswith check
  454. *
  455. * TODO AV - enhance to support "char.sss" ie FQN direclty (match iff equals)
  456. * we could also add support for "*..*charss" endsWith style?
  457. *
  458. * @param typePattern
  459. * @return null if not possible, or the startWith sequence to test against
  460. */
  461. private String looksLikeStartsWith(String typePattern) {
  462. if (typePattern.indexOf('@') >= 0
  463. || typePattern.indexOf('+') >= 0
  464. || typePattern.indexOf(' ') >= 0
  465. || typePattern.charAt(typePattern.length()-1) != '*') {
  466. return null;
  467. }
  468. // now must looks like with "charsss..*" or "cha.rss..*" etc
  469. // note that "*" and "*..*" won't be fast matched
  470. // and that "charsss.*" will not neither
  471. int length = typePattern.length();
  472. if (typePattern.endsWith("..*") && length > 3) {
  473. if (typePattern.indexOf("..") == length-3 // no ".." before last sequence
  474. && typePattern.indexOf('*') == length-1) { // no "*" before last sequence
  475. return typePattern.substring(0, length-2).replace('$', '.');
  476. // ie "charsss." or "char.rss." etc
  477. }
  478. }
  479. return null;
  480. }
  481. /**
  482. * Register the dump filter
  483. *
  484. * @param weaver
  485. * @param loader
  486. * @param definitions
  487. */
  488. private void registerDump(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  489. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  490. Definition definition = (Definition) iterator.next();
  491. for (Iterator iterator1 = definition.getDumpPatterns().iterator(); iterator1.hasNext();) {
  492. String dump = (String) iterator1.next();
  493. TypePattern pattern = new PatternParser(dump).parseTypePattern();
  494. m_dumpTypePattern.add(pattern);
  495. }
  496. if (definition.shouldDumpBefore()) {
  497. m_dumpBefore = true;
  498. }
  499. }
  500. }
  501. protected boolean accept(String className, byte[] bytes) {
  502. // avoid ResolvedType if not needed
  503. if (m_excludeTypePattern.isEmpty() && m_includeTypePattern.isEmpty()) {
  504. return true;
  505. }
  506. // still try to avoid ResolvedType if we have simple patterns
  507. String fastClassName = className.replace('/', '.').replace('$', '.');
  508. for (int i = 0; i < m_excludeStartsWith.size(); i++) {
  509. if (fastClassName.startsWith((String)m_excludeStartsWith.get(i))) {
  510. return false;
  511. }
  512. }
  513. /*
  514. * Bug 120363
  515. * If we have an exclude pattern that cannot be matched using "starts with"
  516. * then we cannot fast accept
  517. */
  518. if (m_excludeTypePattern.isEmpty()) {
  519. boolean fastAccept = false;//defaults to false if no fast include
  520. for (int i = 0; i < m_includeStartsWith.size(); i++) {
  521. fastAccept = fastClassName.startsWith((String)m_includeStartsWith.get(i));
  522. if (fastAccept) {
  523. break;
  524. }
  525. }
  526. }
  527. // needs further analysis
  528. // TODO AV - needs refactoring
  529. // during LTW this calling resolve at that stage is BAD as we do have the bytecode from the classloader hook
  530. // but still go thru resolve that will do a getResourcesAsStream on disk
  531. // this is also problematic for jit stub which are not on disk - as often underlying infra
  532. // does returns null or some other info for getResourceAsStream (f.e. WLS 9 CR248491)
  533. // Instead I parse the given bytecode. But this also means it will be parsed again in
  534. // new WeavingClassFileProvider() from WeavingAdaptor.getWovenBytes()...
  535. ensureDelegateInitialized(className,bytes);
  536. ResolvedType classInfo = delegateForCurrentClass.getResolvedTypeX();//BAD: weaver.getWorld().resolve(UnresolvedType.forName(className), true);
  537. //exclude are "AND"ed
  538. for (Iterator iterator = m_excludeTypePattern.iterator(); iterator.hasNext();) {
  539. TypePattern typePattern = (TypePattern) iterator.next();
  540. if (typePattern.matchesStatically(classInfo)) {
  541. // exclude match - skip
  542. return false;
  543. }
  544. }
  545. //include are "OR"ed
  546. boolean accept = true;//defaults to true if no include
  547. for (Iterator iterator = m_includeTypePattern.iterator(); iterator.hasNext();) {
  548. TypePattern typePattern = (TypePattern) iterator.next();
  549. accept = typePattern.matchesStatically(classInfo);
  550. if (accept) {
  551. break;
  552. }
  553. // goes on if this include did not match ("OR"ed)
  554. }
  555. return accept;
  556. }
  557. //FIXME we don't use include/exclude of others aop.xml
  558. //this can be nice but very dangerous as well to change that
  559. private boolean acceptAspect(String aspectClassName) {
  560. // avoid ResolvedType if not needed
  561. if (m_aspectExcludeTypePattern.isEmpty() && m_aspectIncludeTypePattern.isEmpty()) {
  562. return true;
  563. }
  564. // still try to avoid ResolvedType if we have simple patterns
  565. // EXCLUDE: if one match then reject
  566. String fastClassName = aspectClassName.replace('/', '.').replace('.', '$');
  567. for (int i = 0; i < m_aspectExcludeStartsWith.size(); i++) {
  568. if (fastClassName.startsWith((String)m_aspectExcludeStartsWith.get(i))) {
  569. return false;
  570. }
  571. }
  572. //INCLUDE: if one match then accept
  573. for (int i = 0; i < m_aspectIncludeStartsWith.size(); i++) {
  574. if (fastClassName.startsWith((String)m_aspectIncludeStartsWith.get(i))) {
  575. return true;
  576. }
  577. }
  578. // needs further analysis
  579. ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(aspectClassName), true);
  580. //exclude are "AND"ed
  581. for (Iterator iterator = m_aspectExcludeTypePattern.iterator(); iterator.hasNext();) {
  582. TypePattern typePattern = (TypePattern) iterator.next();
  583. if (typePattern.matchesStatically(classInfo)) {
  584. // exclude match - skip
  585. return false;
  586. }
  587. }
  588. //include are "OR"ed
  589. boolean accept = true;//defaults to true if no include
  590. for (Iterator iterator = m_aspectIncludeTypePattern.iterator(); iterator.hasNext();) {
  591. TypePattern typePattern = (TypePattern) iterator.next();
  592. accept = typePattern.matchesStatically(classInfo);
  593. if (accept) {
  594. break;
  595. }
  596. // goes on if this include did not match ("OR"ed)
  597. }
  598. return accept;
  599. }
  600. protected boolean shouldDump(String className, boolean before) {
  601. // Don't dump before weaving unless asked to
  602. if (before && !m_dumpBefore) {
  603. return false;
  604. }
  605. // avoid ResolvedType if not needed
  606. if (m_dumpTypePattern.isEmpty()) {
  607. return false;
  608. }
  609. //TODO AV - optimize for className.startWith only
  610. ResolvedType classInfo = weaver.getWorld().resolve(UnresolvedType.forName(className), true);
  611. //dump
  612. for (Iterator iterator = m_dumpTypePattern.iterator(); iterator.hasNext();) {
  613. TypePattern typePattern = (TypePattern) iterator.next();
  614. if (typePattern.matchesStatically(classInfo)) {
  615. // dump match
  616. return true;
  617. }
  618. }
  619. return false;
  620. }
  621. /*
  622. * shared classes methods
  623. */
  624. /**
  625. * @return Returns the key.
  626. */
  627. public String getNamespace() {
  628. // System.out.println("ClassLoaderWeavingAdaptor.getNamespace() classloader=" + weavingContext.getClassLoaderName() + ", namespace=" + namespace);
  629. if(namespace==null) return "";
  630. else return new String(namespace);
  631. }
  632. /**
  633. * Check to see if any classes are stored in the generated classes cache.
  634. * Then flush the cache if it is not empty
  635. * @param className TODO
  636. * @return true if a class has been generated and is stored in the cache
  637. */
  638. public boolean generatedClassesExistFor (String className) {
  639. // System.err.println("? ClassLoaderWeavingAdaptor.generatedClassesExist() classname=" + className + ", size=" + generatedClasses);
  640. if (className == null) return !generatedClasses.isEmpty();
  641. else return generatedClasses.containsKey(className);
  642. }
  643. /**
  644. * Flush the generated classes cache
  645. */
  646. public void flushGeneratedClasses() {
  647. // System.err.println("? ClassLoaderWeavingAdaptor.flushGeneratedClasses() generatedClasses=" + generatedClasses);
  648. generatedClasses = new HashMap();
  649. }
  650. private void defineClass(ClassLoader loader, String name, byte[] bytes) {
  651. if (trace.isTraceEnabled()) trace.enter("defineClass",this,new Object[] {loader,name,bytes});
  652. Object clazz = null;
  653. debug("generating class '" + name + "'");
  654. try {
  655. //TODO av protection domain, and optimize
  656. Method defineClass = ClassLoader.class.getDeclaredMethod(
  657. "defineClass", new Class[] { String.class,
  658. bytes.getClass(), int.class, int.class });
  659. defineClass.setAccessible(true);
  660. clazz = defineClass.invoke(loader, new Object[] { name, bytes,
  661. new Integer(0), new Integer(bytes.length) });
  662. } catch (InvocationTargetException e) {
  663. if (e.getTargetException() instanceof LinkageError) {
  664. warn("define generated class failed",e.getTargetException());
  665. //is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
  666. // TODO maw I don't think this is OK and
  667. } else {
  668. warn("define generated class failed",e.getTargetException());
  669. }
  670. } catch (Exception e) {
  671. warn("define generated class failed",e);
  672. }
  673. if (trace.isTraceEnabled()) trace.exit("defineClass",clazz);
  674. }
  675. }