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);
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 }