View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.transform.delegation;
9   
10  import java.util.ArrayList;
11  import java.util.Hashtable;
12  import java.util.Iterator;
13  import java.util.List;
14  
15  import org.codehaus.aspectwerkz.transform.AspectWerkzPreProcessor;
16  import org.codehaus.aspectwerkz.transform.Context;
17  import org.codehaus.aspectwerkz.transform.Transformer;
18  import org.codehaus.aspectwerkz.transform.WeavingStrategy;
19  
20  /***
21   * A weaving strategy implementing a weaving scheme based on delegation.
22   *
23   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
24   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> 
25   */
26  public class DelegationWeavingStrategy implements WeavingStrategy {
27      /***
28       * The transformation m_stack
29       */
30      private List m_stack;
31  
32      /***
33       * The transformer to add serial ver uid Out of the transformation stack to be applied only if class is weaved
34       */
35      private Transformer m_addSerialVerUidTransformer;
36  
37      /***
38       * Initializes the transformer stack.
39       *
40       * @param params not used
41       */
42      public void initialize(final Hashtable params) {
43          m_addSerialVerUidTransformer = new AddSerialVersionUidTransformer();
44  
45          // CAUTION: ORDER IS IMPORTANT!
46          m_stack = new ArrayList();
47          m_stack.add(new PrepareAdvisedClassTransformer());
48          m_stack.add(new AddInterfaceTransformer());
49          m_stack.add(new AddImplementationTransformer());
50          // we add PrepareAdvisedClassTF twice - to match on introduce method and allow for Javassist
51          // code compilation on __AW_joinPointManager field
52          m_stack.add(new PrepareAdvisedClassTransformer());
53          m_stack.add(new FieldSetGetTransformer());
54          m_stack.add(new MethodCallTransformer());
55          m_stack.add(new ConstructorCallTransformer());
56          m_stack.add(new MethodExecutionTransformer());
57          m_stack.add(new ConstructorExecutionTransformer());
58          m_stack.add(new HandlerTransformer());
59      }
60  
61      /***
62       * Transforms the class.
63       *
64       * @param className
65       * @param context
66       */
67      public void transform(final String className, final Context context) {
68          boolean advisedAtLeastOnce = false;
69          Klass klass = (Klass) context.getClassAbstraction();
70          for (Iterator it = m_stack.iterator(); it.hasNext();) {
71              Object transformer = it.next();
72              if (transformer instanceof Transformer) {
73                  Transformer tf = (Transformer) transformer;
74                  context.resetAdvised();
75                  try {
76                      tf.transform(context, klass);
77                  } catch (Exception e) {
78                      e.printStackTrace();
79                  }
80                  if (context.isAdvised()) {
81                      advisedAtLeastOnce = true;
82                  }
83                  if (context.isAdvised()) {
84                      AspectWerkzPreProcessor.log(" " + className + " <- " + transformer.getClass().getName());
85                  }
86              }
87          }
88          // handle the serial version uid only if class was advised
89          if (advisedAtLeastOnce) {
90              try {
91                  m_addSerialVerUidTransformer.transform(context, klass);
92              } catch (Exception e) {
93                  System.err.println(
94                          "WARNING: could not add new serial version UID to class [" + klass.getName() +
95                          "] and this  might cause problems with serialization"
96                  );
97                  e.printStackTrace();
98              }
99          }
100     }
101 
102     /***
103      * Creates a new transformation context.
104      *
105      * @param name
106      * @param bytecode
107      * @param loader
108      * @return
109      */
110     public Context newContext(final String name, final byte[] bytecode, final ClassLoader loader) {
111         return new ContextImpl(name, bytecode, loader);
112     }
113 }