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

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