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

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