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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*******************************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Common Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/cpl-v10.html
  7. *
  8. * Contributors:
  9. * Alexandre Vasseur initial implementation
  10. *******************************************************************************/
  11. package org.aspectj.weaver.loadtime;
  12. import org.aspectj.weaver.tools.WeavingAdaptor;
  13. import org.aspectj.weaver.tools.GeneratedClassHandler;
  14. import org.aspectj.weaver.patterns.TypePattern;
  15. import org.aspectj.weaver.patterns.PatternParser;
  16. import org.aspectj.weaver.bcel.BcelWorld;
  17. import org.aspectj.weaver.bcel.BcelWeaver;
  18. import org.aspectj.weaver.ICrossReferenceHandler;
  19. import org.aspectj.weaver.World;
  20. import org.aspectj.weaver.ResolvedTypeX;
  21. import org.aspectj.weaver.TypeX;
  22. import org.aspectj.weaver.loadtime.definition.DocumentParser;
  23. import org.aspectj.weaver.loadtime.definition.Definition;
  24. import org.aspectj.bridge.ISourceLocation;
  25. import org.aspectj.bridge.Message;
  26. import org.aspectj.bridge.IMessage;
  27. import org.aspectj.asm.IRelationship;
  28. import java.util.List;
  29. import java.util.ArrayList;
  30. import java.util.Enumeration;
  31. import java.util.Iterator;
  32. import java.io.File;
  33. import java.io.IOException;
  34. import java.net.URL;
  35. /**
  36. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  37. */
  38. public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
  39. //ATAJ LTW include/exclude
  40. private List m_includeTypePattern = new ArrayList();
  41. private List m_excludeTypePattern = new ArrayList();
  42. private List m_aspectExcludeTypePattern = new ArrayList();
  43. public void addIncludeTypePattern(TypePattern typePattern) {
  44. m_includeTypePattern.add(typePattern);
  45. }
  46. public void addExcludeTypePattern(TypePattern typePattern) {
  47. m_excludeTypePattern.add(typePattern);
  48. }
  49. public void addAspectExcludeTypePattern(TypePattern typePattern) {
  50. m_aspectExcludeTypePattern.add(typePattern);
  51. }
  52. public ClassLoaderWeavingAdaptor(final ClassLoader loader) {
  53. super(null);// at this stage we don't have yet a generatedClassHandler to define to the VM the closures
  54. this.generatedClassHandler = new GeneratedClassHandler() {
  55. /**
  56. * Callback when we need to define a Closure in the JVM
  57. *
  58. * @param name
  59. * @param bytes
  60. */
  61. public void acceptClass(String name, byte[] bytes) {
  62. //TODO av make dump configurable
  63. try {
  64. Aj.__dump(name, bytes);
  65. } catch (Throwable throwable) {
  66. throwable.printStackTrace();
  67. }
  68. Aj.defineClass(loader, name, bytes);// could be done lazily using the hook
  69. }
  70. };
  71. bcelWorld = new BcelWorld(
  72. loader, messageHandler, new ICrossReferenceHandler() {
  73. public void addCrossReference(ISourceLocation from, ISourceLocation to, IRelationship.Kind kind, boolean runtimeTest) {
  74. ;// for tools only
  75. }
  76. }
  77. );
  78. // //TODO this AJ code will call
  79. // //org.aspectj.apache.bcel.Repository.setRepository(this);
  80. // //ie set some static things
  81. // //==> bogus as Bcel is expected to be
  82. // org.aspectj.apache.bcel.Repository.setRepository(new ClassLoaderRepository(loader));
  83. weaver = new BcelWeaver(bcelWorld);
  84. // register the definitions
  85. registerDefinitions(weaver, loader);
  86. // after adding aspects
  87. weaver.prepareForWeave();
  88. }
  89. /**
  90. * Load and cache the aop.xml/properties according to the classloader visibility rules
  91. *
  92. * @param weaver
  93. * @param loader
  94. */
  95. private void registerDefinitions(final BcelWeaver weaver, final ClassLoader loader) {
  96. try {
  97. //TODO av underoptimized: we will parse each XML once per CL that see it
  98. Enumeration xmls = loader.getResources("/META-INF/aop.xml");
  99. List definitions = new ArrayList();
  100. //TODO av dev mode needed ? TBD -Daj5.def=...
  101. if (loader != null && loader != ClassLoader.getSystemClassLoader().getParent()) {
  102. String file = System.getProperty("aj5.def", null);
  103. if (file != null) {
  104. definitions.add(DocumentParser.parse((new File(file)).toURL()));
  105. }
  106. }
  107. while (xmls.hasMoreElements()) {
  108. URL xml = (URL) xmls.nextElement();
  109. definitions.add(DocumentParser.parse(xml));
  110. }
  111. registerOptions(weaver, loader, definitions);
  112. registerAspectExclude(weaver, loader, definitions);
  113. registerAspects(weaver, loader, definitions);
  114. registerIncludeExclude(weaver, loader, definitions);
  115. } catch (Exception e) {
  116. weaver.getWorld().getMessageHandler().handleMessage(
  117. new Message("Register definition failed", IMessage.FAIL, e, null)
  118. );
  119. }
  120. }
  121. /**
  122. * Configure the weaver according to the option directives
  123. * TODO av - don't know if it is that good to reuse, since we only allow a small subset of options in LTW
  124. *
  125. * @param weaver
  126. * @param loader
  127. * @param definitions
  128. */
  129. private void registerOptions(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  130. StringBuffer allOptions = new StringBuffer();
  131. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  132. Definition definition = (Definition) iterator.next();
  133. allOptions.append(definition.getWeaverOptions()).append(' ');
  134. }
  135. Options.WeaverOption weaverOption = Options.parse(allOptions.toString(), loader);
  136. // configure the weaver and world
  137. // AV - code duplicates AspectJBuilder.initWorldAndWeaver()
  138. World world = weaver.getWorld();
  139. world.setMessageHandler(weaverOption.messageHandler);
  140. world.setXlazyTjp(weaverOption.lazyTjp);
  141. weaver.setReweavableMode(weaverOption.reWeavable, false);
  142. world.setXnoInline(weaverOption.noInline);
  143. world.setBehaveInJava5Way(weaverOption.java5);
  144. //TODO proceedOnError option
  145. }
  146. private void registerAspectExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  147. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  148. Definition definition = (Definition) iterator.next();
  149. for (Iterator iterator1 = definition.getAspectExcludePatterns().iterator(); iterator1.hasNext();) {
  150. String exclude = (String) iterator1.next();
  151. TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
  152. m_aspectExcludeTypePattern.add(excludePattern);
  153. }
  154. }
  155. }
  156. /**
  157. * Register the aspect, following include / exclude rules
  158. *
  159. * @param weaver
  160. * @param loader
  161. * @param definitions
  162. */
  163. private void registerAspects(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  164. //TODO: the exclude aspect allow to exclude aspect defined upper in the CL hierarchy - is it what we want ??
  165. // if not, review the getResource so that we track which resource is defined by which CL
  166. //it aspectClassNames
  167. //exclude if in any of the exclude list
  168. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  169. Definition definition = (Definition) iterator.next();
  170. for (Iterator aspects = definition.getAspectClassNames().iterator(); aspects.hasNext();) {
  171. String aspectClassName = (String) aspects.next();
  172. if (acceptAspect(aspectClassName)) {
  173. weaver.addLibraryAspect(aspectClassName);
  174. }
  175. }
  176. }
  177. //it concreteAspects
  178. //exclude if in any of the exclude list
  179. //TODO
  180. }
  181. /**
  182. * Register the include / exclude filters
  183. *
  184. * @param weaver
  185. * @param loader
  186. * @param definitions
  187. */
  188. private void registerIncludeExclude(final BcelWeaver weaver, final ClassLoader loader, final List definitions) {
  189. for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
  190. Definition definition = (Definition) iterator.next();
  191. for (Iterator iterator1 = definition.getIncludePatterns().iterator(); iterator1.hasNext();) {
  192. String include = (String) iterator1.next();
  193. TypePattern includePattern = new PatternParser(include).parseTypePattern();
  194. m_includeTypePattern.add(includePattern);
  195. }
  196. for (Iterator iterator1 = definition.getExcludePatterns().iterator(); iterator1.hasNext();) {
  197. String exclude = (String) iterator1.next();
  198. TypePattern excludePattern = new PatternParser(exclude).parseTypePattern();
  199. m_excludeTypePattern.add(excludePattern);
  200. }
  201. }
  202. }
  203. protected boolean accept(String className) {
  204. // avoid ResolvedType if not needed
  205. if (m_excludeTypePattern.isEmpty() && m_includeTypePattern.isEmpty()) {
  206. return true;
  207. }
  208. //TODO AV - optimize for className.startWith only
  209. ResolvedTypeX classInfo = weaver.getWorld().getCoreType(TypeX.forName(className));
  210. //exclude
  211. for (Iterator iterator = m_excludeTypePattern.iterator(); iterator.hasNext();) {
  212. TypePattern typePattern = (TypePattern) iterator.next();
  213. if (typePattern.matchesStatically(classInfo)) {
  214. // exclude match - skip
  215. return false;
  216. }
  217. }
  218. for (Iterator iterator = m_includeTypePattern.iterator(); iterator.hasNext();) {
  219. TypePattern typePattern = (TypePattern) iterator.next();
  220. if (! typePattern.matchesStatically(classInfo)) {
  221. // include does not match - skip
  222. return false;
  223. }
  224. }
  225. return true;
  226. }
  227. private boolean acceptAspect(String aspectClassName) {
  228. // avoid ResolvedType if not needed
  229. if (m_aspectExcludeTypePattern.isEmpty()) {
  230. return true;
  231. }
  232. //TODO AV - optimize for className.startWith only
  233. ResolvedTypeX classInfo = weaver.getWorld().getCoreType(TypeX.forName(aspectClassName));
  234. //exclude
  235. for (Iterator iterator = m_aspectExcludeTypePattern.iterator(); iterator.hasNext();) {
  236. TypePattern typePattern = (TypePattern) iterator.next();
  237. if (typePattern.matchesStatically(classInfo)) {
  238. // exclude match - skip
  239. return false;
  240. }
  241. }
  242. return true;
  243. }
  244. }