KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > CtConstructor


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist;
17
18 import javassist.bytecode.*;
19 import javassist.compiler.Javac;
20 import javassist.compiler.CompileError;
21
22 /**
23  * An instance of CtConstructor represents a constructor.
24  * It may represent a static constructor
25  * (class initializer). To distinguish a constructor and a class
26  * initializer, call <code>isClassInitializer()</code>.
27  *
28  * <p>See the super class <code>CtBehavior</code> as well since
29  * a number of useful methods are in <code>CtBehavior</code>.
30  *
31  * @see CtClass#getDeclaredConstructors()
32  * @see CtClass#getClassInitializer()
33  * @see CtNewConstructor
34  */

35 public final class CtConstructor extends CtBehavior {
36     protected CtConstructor(MethodInfo minfo, CtClass declaring) {
37         super(declaring, minfo);
38         next = null;
39     }
40
41     /**
42      * Creates a constructor with no constructor body.
43      * The created constructor
44      * must be added to a class with <code>CtClass.addConstructor()</code>.
45      *
46      * <p>The created constructor does not include a constructor body,
47      * must be specified with <code>setBody()</code>.
48      *
49      * @param declaring the class to which the created method is added.
50      * @param parameters a list of the parameter types
51      *
52      * @see CtClass#addConstructor(CtConstructor)
53      * @see CtConstructor#setBody(String)
54      * @see CtConstructor#setBody(CtConstructor,ClassMap)
55      */

56     public CtConstructor(CtClass[] parameters, CtClass declaring) {
57         this((MethodInfo)null, declaring);
58         ConstPool cp = declaring.getClassFile2().getConstPool();
59         String JavaDoc desc = Descriptor.ofConstructor(parameters);
60         methodInfo = new MethodInfo(cp, "<init>", desc);
61         setModifiers(Modifier.PUBLIC);
62     }
63
64     /**
65      * Creates a copy of a <code>CtConstructor</code> object.
66      * The created constructor must be
67      * added to a class with <code>CtClass.addConstructor()</code>.
68      *
69      * <p>All occurrences of class names in the created constructor
70      * are replaced with names specified by
71      * <code>map</code> if <code>map</code> is not <code>null</code>.
72      *
73      * <p>By default, all the occurrences of the names of the class
74      * declaring <code>src</code> and the superclass are replaced
75      * with the name of the class and the superclass that
76      * the created constructor is added to.
77      * This is done whichever <code>map</code> is null or not.
78      * To prevent this replacement, call <code>ClassMap.fix()</code>.
79      *
80      * <p><b>Note:</b> if the <code>.class</code> notation (for example,
81      * <code>String.class</code>) is included in an expression, the
82      * Javac compiler may produce a helper method.
83      * Since this constructor never
84      * copies this helper method, the programmers have the responsiblity of
85      * copying it. Otherwise, use <code>Class.forName()</code> in the
86      * expression.
87      *
88      * @param src the source method.
89      * @param declaring the class to which the created method is added.
90      * @param map the hashtable associating original class names
91      * with substituted names.
92      * It can be <code>null</code>.
93      *
94      * @see CtClass#addConstructor(CtConstructor)
95      * @see ClassMap#fix(String)
96      */

97     public CtConstructor(CtConstructor src, CtClass declaring, ClassMap map)
98         throws CannotCompileException
99     {
100         this((MethodInfo)null, declaring);
101         MethodInfo srcInfo = src.methodInfo;
102         CtClass srcClass = src.getDeclaringClass();
103         ConstPool cp = declaring.getClassFile2().getConstPool();
104         if (map == null)
105             map = new ClassMap();
106
107         map.put(srcClass.getName(), declaring.getName());
108         try {
109             boolean patch = false;
110             CtClass srcSuper = srcClass.getSuperclass();
111             String JavaDoc destSuperName = declaring.getSuperclass().getName();
112             if (srcSuper != null) {
113                 String JavaDoc srcSuperName = srcSuper.getName();
114                 if (!srcSuperName.equals(destSuperName))
115                     if (srcSuperName.equals(CtClass.javaLangObject))
116                         patch = true;
117                     else
118                         map.put(srcSuperName, destSuperName);
119             }
120
121             methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
122             if (patch)
123                 methodInfo.setSuperclass(destSuperName);
124         }
125         catch (NotFoundException e) {
126             throw new CannotCompileException(e);
127         }
128         catch (BadBytecode e) {
129             throw new CannotCompileException(e);
130         }
131     }
132
133     /**
134      * Returns true if this object represents a constructor.
135      */

136     public boolean isConstructor() {
137         return methodInfo.isConstructor();
138     }
139
140     /**
141      * Returns true if this object represents a static initializer.
142      */

143     public boolean isClassInitializer() {
144         return methodInfo.isStaticInitializer();
145     }
146
147     /**
148      * Obtains the name of this constructor.
149      * It is the same as the simple name of the class declaring this
150      * constructor. If this object represents a class initializer,
151      * then this method returns <code>"&lt;clinit&gt;"</code>.
152      */

153     public String JavaDoc getName() {
154         if (methodInfo.isStaticInitializer())
155             return MethodInfo.nameClinit;
156         else
157             return declaringClass.getSimpleName();
158     }
159
160     /**
161      * Returns true if the constructor is the default one.
162      */

163     public boolean isEmpty() {
164         CodeAttribute ca = getMethodInfo2().getCodeAttribute();
165         if (ca == null)
166             return false; // native or abstract??
167
// they are not allowed, though.
168

169         ConstPool cp = ca.getConstPool();
170         CodeIterator it = ca.iterator();
171         try {
172             int pos, desc;
173             return it.byteAt(it.next()) == Opcode.ALOAD_0
174                 && it.byteAt(pos = it.next()) == Opcode.INVOKESPECIAL
175                 && (desc = cp.isConstructor(CtClass.javaLangObject,
176                                             it.u16bitAt(pos + 1))) != 0
177                 && cp.getUtf8Info(desc).equals("()V")
178                 && it.byteAt(it.next()) == Opcode.RETURN
179                 && !it.hasNext();
180         }
181         catch (BadBytecode e) {}
182         return false;
183     }
184
185     /**
186      * Sets a constructor body.
187      *
188      * @param src the source code representing the constructor body.
189      * It must be a single statement or block.
190      * If it is <code>null</code>, the substituted
191      * constructor body does nothing except calling
192      * <code>super()</code>.
193      */

194     public void setBody(String JavaDoc src) throws CannotCompileException {
195         if (src == null)
196             if (isClassInitializer())
197                 src = ";";
198             else
199                 src = "super();";
200
201         super.setBody(src);
202     }
203
204     /**
205      * Copies a constructor body from another constructor.
206      *
207      * <p>All occurrences of the class names in the copied body
208      * are replaced with the names specified by
209      * <code>map</code> if <code>map</code> is not <code>null</code>.
210      *
211      * @param src the method that the body is copied from.
212      * @param map the hashtable associating original class names
213      * with substituted names.
214      * It can be <code>null</code>.
215      */

216     public void setBody(CtConstructor src, ClassMap map)
217         throws CannotCompileException
218     {
219         setBody0(src.declaringClass, src.methodInfo,
220                  declaringClass, methodInfo, map);
221     }
222
223     /**
224      * Inserts bytecode just after another constructor in the super class
225      * or this class is called.
226      * It does not work if this object represents a class initializer.
227      *
228      * @param src the source code representing the inserted bytecode.
229      * It must be a single statement or block.
230      */

231     public void insertBeforeBody(String JavaDoc src) throws CannotCompileException {
232         declaringClass.checkModify();
233         if (isClassInitializer())
234             throw new CannotCompileException("class initializer");
235
236         CodeAttribute ca = methodInfo.getCodeAttribute();
237         CodeIterator iterator = ca.iterator();
238         Bytecode b = new Bytecode(methodInfo.getConstPool(),
239                                   ca.getMaxStack(), ca.getMaxLocals());
240         b.setStackDepth(ca.getMaxStack());
241         Javac jv = new Javac(b, declaringClass);
242         try {
243             jv.recordParams(getParameterTypes(), false);
244             jv.compileStmnt(src);
245             ca.setMaxStack(b.getMaxStack());
246             ca.setMaxLocals(b.getMaxLocals());
247             iterator.skipConstructor();
248             int pos = iterator.insertEx(b.get());
249             iterator.insert(b.getExceptionTable(), pos);
250         }
251         catch (NotFoundException e) {
252             throw new CannotCompileException(e);
253         }
254         catch (CompileError e) {
255             throw new CannotCompileException(e);
256         }
257         catch (BadBytecode e) {
258             throw new CannotCompileException(e);
259         }
260     }
261
262     /* This method is called by addCatch() in CtBehavior.
263      * super() and this() must not be in a try statement.
264      */

265     int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException {
266         CodeIterator ci = ca.iterator();
267         try {
268             ci.skipConstructor();
269             return ci.next();
270         }
271         catch (BadBytecode e) {
272             throw new CannotCompileException(e);
273         }
274     }
275 }
276
Popular Tags