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 org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
11  
12  import javassist.ByteArrayClassPath;
13  import javassist.ClassPool;
14  import javassist.CtClass;
15  import javassist.LoaderClassPath;
16  
17  /***
18   * The AspectWerkz class concept. <p/>Contains informations and data about the class being transformed.
19   * 
20   * @TODO: contains javassist specific stuff, refactor out and use an abstraction
21   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
22   * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
23   */
24  public class Klass {
25      /***
26       * The name of the class.
27       */
28      private final String m_name;
29  
30      /***
31       * The classloader defining the class
32       */
33      private final ClassLoader m_loader;
34  
35      /***
36       * The Javassist CtClass, lazyly loaded.
37       */
38      private CtClass m_ctClass;
39  
40      /***
41       * The Javassist initial class gen to calculate serial ver uid based on initial bytecode Lazily initialized
42       */
43      private CtClass m_initialCtClass;
44  
45      /***
46       * The initial bytecode of the class
47       */
48      private final byte[] m_initialBytecode;
49  
50      /***
51       * The join point index.
52       */
53      private int m_joinPointIndex = -1;
54  
55      /***
56       * Creates a new class.
57       * 
58       * @param name the name
59       * @param bytecode the byte code
60       */
61      public Klass(final String name, final byte[] bytecode, final ClassLoader loader) {
62          m_name = name.replace('/', '.');
63          m_loader = loader;
64          m_initialBytecode = bytecode;
65      }
66  
67      /***
68       * Returns the name of the class.
69       * 
70       * @return the name
71       */
72      public String getName() {
73          return m_name;
74      }
75  
76      /***
77       * Returns the Javassist class gen for the class.
78       * 
79       * @return the class gen
80       */
81      public CtClass getCtClass() {
82          if (m_ctClass == null) {
83              m_ctClass = fromByte(m_name, m_initialBytecode, m_loader);
84          }
85          return m_ctClass;
86      }
87  
88      /***
89       * Returns the Javassist initial class gen for the class.
90       * 
91       * @return the initial class gen
92       */
93      public CtClass getInitialCtClass() {
94          if (m_initialCtClass == null) {
95              m_initialCtClass = fromByte(m_name, m_initialBytecode, m_loader);
96          }
97          return m_initialCtClass;
98      }
99  
100     /***
101      * Returns the byte code for the class.
102      * 
103      * @return
104      */
105     public byte[] getBytecode() {
106         try {
107             return getCtClass().toBytecode();
108         } catch (Exception e) {
109             throw new WrappedRuntimeException(e);
110         }
111     }
112 
113     /***
114      * Transforms byte code to a Javassist class gen.
115      * 
116      * @param bytecode the byte code
117      * @return the Javassist class gen
118      */
119     private static CtClass fromByte(final String name, final byte[] bytecode, final ClassLoader loader) {
120         try {
121             ClassPool cp = new ClassPool(null);
122             cp.insertClassPath(new ByteArrayClassPath(name, bytecode));
123             cp.appendClassPath(new LoaderClassPath(loader));
124             CtClass klass = cp.get(name);
125             klass.stopPruning(true);// to allow dump
126             return klass;
127         } catch (Exception e) {
128             throw new WrappedRuntimeException(e);
129         }
130     }
131 
132     /***
133      * Returns the current join point index.
134      * 
135      * @return
136      */
137     public int getJoinPointIndex() {
138         if (m_joinPointIndex != -1) {
139             return m_joinPointIndex;
140         } else {
141             m_joinPointIndex = JavassistHelper.getJoinPointIndex(getCtClass());
142             return m_joinPointIndex;
143         }
144     }
145 
146     /***
147      * Increments the join point index.
148      */
149     public void incrementJoinPointIndex() {
150         getJoinPointIndex();
151         m_joinPointIndex++;
152     }
153 
154     /***
155      * Flushes the index count.
156      */
157     public void flushJoinPointIndex() {
158         if (m_joinPointIndex != -1) {
159             JavassistHelper.setJoinPointIndex(getCtClass(), m_joinPointIndex);
160         }
161     }
162 }