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.

Aj.java 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. *******************************************************************************/
  12. package org.aspectj.weaver.loadtime;
  13. import java.io.File;
  14. import java.io.FileOutputStream;
  15. import java.lang.reflect.Method;
  16. import java.util.Map;
  17. import java.util.WeakHashMap;
  18. import org.aspectj.weaver.tools.WeavingAdaptor;
  19. /**
  20. * Adapter between the generic class pre processor interface and the AspectJ weaver
  21. * Load time weaving consistency relies on Bcel.setRepository
  22. *
  23. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  24. */
  25. public class Aj implements ClassPreProcessor {
  26. /**
  27. * Initialization
  28. */
  29. public void initialize() {
  30. ;
  31. }
  32. /**
  33. * Weave
  34. *
  35. * @param className
  36. * @param bytes
  37. * @param loader
  38. * @return
  39. */
  40. public byte[] preProcess(String className, byte[] bytes, ClassLoader loader) {
  41. //TODO AV needs to doc that
  42. if (loader == null || className == null) {
  43. // skip boot loader or null classes (hibernate)
  44. return bytes;
  45. }
  46. try {
  47. byte[] weaved = WeaverContainer.getWeaver(loader).weaveClass(className, bytes);
  48. //FIXME AV make dump optionnal and configurable
  49. __dump(className, weaved);
  50. return weaved;
  51. } catch (Throwable t) {
  52. //FIXME AV wondering if we should have the option to fail (throw runtime exception) here
  53. // would make sense at least in test f.e. see TestHelper.handleMessage()
  54. t.printStackTrace();
  55. return bytes;
  56. }
  57. }
  58. /**
  59. * Cache of weaver
  60. * There is one weaver per classloader
  61. */
  62. static class WeaverContainer {
  63. private static Map weavingAdaptors = new WeakHashMap();
  64. static WeavingAdaptor getWeaver(ClassLoader loader) {
  65. synchronized (weavingAdaptors) {
  66. WeavingAdaptor weavingAdaptor = (WeavingAdaptor) weavingAdaptors.get(loader);
  67. if (weavingAdaptor == null) {
  68. weavingAdaptor = new ClassLoaderWeavingAdaptor(loader);
  69. weavingAdaptors.put(loader, weavingAdaptor);
  70. }
  71. return weavingAdaptor;
  72. }
  73. }
  74. }
  75. static void defineClass(ClassLoader loader, String name, byte[] bytes) {
  76. try {
  77. //TODO av protection domain, and optimize
  78. Method defineClass = ClassLoader.class.getDeclaredMethod(
  79. "defineClass", new Class[]{
  80. String.class, bytes.getClass(), int.class, int.class
  81. }
  82. );
  83. defineClass.setAccessible(true);
  84. defineClass.invoke(
  85. loader, new Object[]{
  86. name,
  87. bytes,
  88. new Integer(0),
  89. new Integer(bytes.length)
  90. }
  91. );
  92. } catch (Throwable t) {
  93. t.printStackTrace();
  94. }
  95. }
  96. /**
  97. * Dump the given bytcode in _dump/...
  98. *
  99. * @param name
  100. * @param b
  101. * @throws Throwable
  102. */
  103. static void __dump(String name, byte[] b) throws Throwable {
  104. //if (true) return;//FIXME AV have an option
  105. String className = name.replace('.', '/');
  106. final File dir;
  107. if (className.indexOf('/') > 0) {
  108. dir = new File("_dump" + File.separator + className.substring(0, className.lastIndexOf('/')));
  109. } else {
  110. dir = new File("_dump");
  111. }
  112. dir.mkdirs();
  113. String fileName = "_dump" + File.separator + className + ".class";
  114. FileOutputStream os = new FileOutputStream(fileName);
  115. os.write(b);
  116. os.close();
  117. }
  118. }