001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist;
017:
018: import javassist.bytecode.*;
019: import javassist.compiler.Javac;
020: import javassist.compiler.CompileError;
021: import javassist.CtMethod.ConstParameter;
022:
023: /**
024: * A collection of static methods for creating a <code>CtConstructor</code>.
025: * An instance of this class does not make any sense.
026: *
027: * <p>A class initializer (static constructor) cannot be created by the
028: * methods in this class. Call <code>makeClassInitializer()</code> in
029: * <code>CtClass</code> and append code snippet to the body of the class
030: * initializer obtained by <code>makeClassInitializer()</code>.
031: *
032: * @see CtClass#addConstructor(CtConstructor)
033: * @see CtClass#makeClassInitializer()
034: */
035: public class CtNewConstructor {
036: /**
037: * Specifies that no parameters are passed to a super-class'
038: * constructor. That is, the default constructor is invoked.
039: */
040: public static final int PASS_NONE = 0; // call super()
041:
042: /**
043: * Specifies that parameters are converted into an array of
044: * <code>Object</code> and passed to a super-class'
045: * constructor.
046: */
047: public static final int PASS_ARRAY = 1; // an array of parameters
048:
049: /**
050: * Specifies that parameters are passed <i>as is</i>
051: * to a super-class' constructor. The signature of that
052: * constructor must be the same as that of the created constructor.
053: */
054: public static final int PASS_PARAMS = 2;
055:
056: /**
057: * Compiles the given source code and creates a constructor.
058: * The source code must include not only the constructor body
059: * but the whole declaration.
060: *
061: * @param src the source text.
062: * @param declaring the class to which the created constructor is added.
063: */
064: public static CtConstructor make(String src, CtClass declaring)
065: throws CannotCompileException {
066: Javac compiler = new Javac(declaring);
067: try {
068: CtMember obj = compiler.compile(src);
069: if (obj instanceof CtConstructor)
070: return (CtConstructor) obj;
071: } catch (CompileError e) {
072: throw new CannotCompileException(e);
073: }
074:
075: throw new CannotCompileException("not a constructor");
076: }
077:
078: /**
079: * Creates a public constructor.
080: *
081: * @param parameters a list of the parameter types.
082: * @param exceptions a list of the exception types.
083: * @param body the source text of the constructor body.
084: * It must be a block surrounded by <code>{}</code>.
085: * If it is <code>null</code>, the substituted
086: * constructor body does nothing except calling
087: * <code>super()</code>.
088: * @param declaring the class to which the created method is added.
089: */
090: public static CtConstructor make(CtClass[] parameters,
091: CtClass[] exceptions, String body, CtClass declaring)
092: throws CannotCompileException {
093: try {
094: CtConstructor cc = new CtConstructor(parameters, declaring);
095: cc.setExceptionTypes(exceptions);
096: cc.setBody(body);
097: return cc;
098: } catch (NotFoundException e) {
099: throw new CannotCompileException(e);
100: }
101: }
102:
103: /**
104: * Creats a copy of a constructor.
105: *
106: * @param c the copied constructor.
107: * @param declaring the class to which the created method is added.
108: * @param map the hashtable associating original class names
109: * with substituted names.
110: * It can be <code>null</code>.
111: *
112: * @see CtConstructor#CtConstructor(CtConstructor,CtClass,ClassMap)
113: */
114: public static CtConstructor copy(CtConstructor c,
115: CtClass declaring, ClassMap map)
116: throws CannotCompileException {
117: return new CtConstructor(c, declaring, map);
118: }
119:
120: /**
121: * Creates a default (public) constructor.
122: *
123: * <p>The created constructor takes no parameter. It calls
124: * <code>super()</code>.
125: */
126: public static CtConstructor defaultConstructor(CtClass declaring)
127: throws CannotCompileException {
128: CtConstructor cons = new CtConstructor((CtClass[]) null,
129: declaring);
130:
131: ConstPool cp = declaring.getClassFile2().getConstPool();
132: Bytecode code = new Bytecode(cp, 1, 1);
133: code.addAload(0);
134: try {
135: code.addInvokespecial(declaring.getSuperclass(), "<init>",
136: "()V");
137: } catch (NotFoundException e) {
138: throw new CannotCompileException(e);
139: }
140:
141: code.add(Bytecode.RETURN);
142:
143: cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
144: return cons;
145: }
146:
147: /**
148: * Creates a public constructor that only calls a constructor
149: * in the super class. The created constructor receives parameters
150: * specified by <code>parameters</code> but calls the super's
151: * constructor without those parameters (that is, it calls the default
152: * constructor).
153: *
154: * <p>The parameters passed to the created constructor should be
155: * used for field initialization. <code>CtField.Initializer</code>
156: * objects implicitly insert initialization code in constructor
157: * bodies.
158: *
159: * @param parameters parameter types
160: * @param exceptions exception types
161: * @param declaring the class to which the created constructor
162: * is added.
163: * @see CtField.Initializer#byParameter(int)
164: */
165: public static CtConstructor skeleton(CtClass[] parameters,
166: CtClass[] exceptions, CtClass declaring)
167: throws CannotCompileException {
168: return make(parameters, exceptions, PASS_NONE, null, null,
169: declaring);
170: }
171:
172: /**
173: * Creates a public constructor that only calls a constructor
174: * in the super class. The created constructor receives parameters
175: * specified by <code>parameters</code> and calls the super's
176: * constructor with those parameters.
177: *
178: * @param parameters parameter types
179: * @param exceptions exception types
180: * @param declaring the class to which the created constructor
181: * is added.
182: */
183: public static CtConstructor make(CtClass[] parameters,
184: CtClass[] exceptions, CtClass declaring)
185: throws CannotCompileException {
186: return make(parameters, exceptions, PASS_PARAMS, null, null,
187: declaring);
188: }
189:
190: /**
191: * Creates a public constructor.
192: *
193: * <p>If <code>howto</code> is <code>PASS_PARAMS</code>,
194: * the created constructor calls the super's constructor with the
195: * same signature. The superclass must contain
196: * a constructor taking the same set of parameters as the created one.
197: *
198: * <p>If <code>howto</code> is <code>PASS_NONE</code>,
199: * the created constructor calls the super's default constructor.
200: * The superclass must contain a constructor taking no parameters.
201: *
202: * <p>If <code>howto</code> is <code>PASS_ARRAY</code>,
203: * the created constructor calls the super's constructor
204: * with the given parameters in the form of an array of
205: * <code>Object</code>. The signature of the super's constructor
206: * must be:
207: *
208: * <ul><code>constructor(Object[] params, <type> cvalue)
209: * </code></ul>
210: *
211: * <p>Here, <code>cvalue</code> is the constant value specified
212: * by <code>cparam</code>.
213: *
214: * <p>If <code>cparam</code> is <code>null</code>, the signature
215: * must be:
216: *
217: * <ul><code>constructor(Object[] params)</code></ul>
218: *
219: * <p>If <code>body</code> is not null, a copy of that method is
220: * embedded in the body of the created constructor.
221: * The embedded method is executed after
222: * the super's constructor is called and the values of fields are
223: * initialized. Note that <code>body</code> must not
224: * be a constructor but a method.
225: *
226: * <p>Since the embedded method is wrapped
227: * in parameter-conversion code
228: * as in <code>CtNewMethod.wrapped()</code>,
229: * the constructor parameters are
230: * passed in the form of an array of <code>Object</code>.
231: * The method specified by <code>body</code> must have the
232: * signature shown below:
233: *
234: * <ul><code>Object method(Object[] params, <type> cvalue)
235: * </code></ul>
236: *
237: * <p>If <code>cparam</code> is <code>null</code>, the signature
238: * must be:
239: *
240: * <ul><code>Object method(Object[] params)</code></ul>
241: *
242: * <p>Although the type of the returned value is <code>Object</code>,
243: * the value must be always <code>null</code>.
244: *
245: * <p><i>Example:</i>
246: *
247: * <ul><pre>ClassPool pool = ... ;
248: * CtClass xclass = pool.makeClass("X");
249: * CtMethod method = pool.getMethod("Sample", "m");
250: * xclass.setSuperclass(pool.get("Y"));
251: * CtClass[] argTypes = { CtClass.intType };
252: * ConstParameter cparam = ConstParameter.string("test");
253: * CtConstructor c = CtNewConstructor.make(argTypes, null,
254: * PASS_PARAMS, method, cparam, xclass);
255: * xclass.addConstructor(c);</pre></ul>
256: *
257: * <p>where the class <code>Sample</code> is as follows:
258: *
259: * <ul><pre>public class Sample {
260: * public Object m(Object[] args, String msg) {
261: * System.out.println(msg);
262: * return null;
263: * }
264: * }</pre></ul>
265: *
266: * <p>This program produces the following class:
267: *
268: * <ul><pre>public class X extends Y {
269: * public X(int p0) {
270: * super(p0);
271: * String msg = "test";
272: * Object[] args = new Object[] { p0 };
273: * // begin of copied body
274: * System.out.println(msg);
275: * Object result = null;
276: * // end
277: * }
278: * }</pre></ul>
279: *
280: * @param parameters a list of the parameter types
281: * @param exceptions a list of the exceptions
282: * @param howto how to pass parameters to the super-class'
283: * constructor (<code>PASS_NONE</code>,
284: * <code>PASS_ARRAY</code>,
285: * or <code>PASS_PARAMS</code>)
286: * @param body appended body (may be <code>null</code>).
287: * It must be not a constructor but a method.
288: * @param cparam constant parameter (may be <code>null</code>.)
289: * @param declaring the class to which the created constructor
290: * is added.
291: *
292: * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
293: */
294: public static CtConstructor make(CtClass[] parameters,
295: CtClass[] exceptions, int howto, CtMethod body,
296: ConstParameter cparam, CtClass declaring)
297: throws CannotCompileException {
298: return CtNewWrappedConstructor.wrapped(parameters, exceptions,
299: howto, body, cparam, declaring);
300: }
301: }
|