1   package org.apache.bcel.generic;
2   
3   /* ====================================================================
4    * The Apache Software License, Version 1.1
5    *
6    * Copyright (c) 2001 The Apache Software Foundation.  All rights
7    * reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
16   * 2. Redistributions in binary form must reproduce the above copyright
17   *    notice, this list of conditions and the following disclaimer in
18   *    the documentation and/or other materials provided with the
19   *    distribution.
20   *
21   * 3. The end-user documentation included with the redistribution,
22   *    if any, must include the following acknowledgment:
23   *       "This product includes software developed by the
24   *        Apache Software Foundation (http://www.apache.org/)."
25   *    Alternately, this acknowledgment may appear in the software itself,
26   *    if and wherever such third-party acknowledgments normally appear.
27   *
28   * 4. The names "Apache" and "Apache Software Foundation" and
29   *    "Apache BCEL" must not be used to endorse or promote products
30   *    derived from this software without prior written permission. For
31   *    written permission, please contact apache@apache.org.
32   *
33   * 5. Products derived from this software may not be called "Apache",
34   *    "Apache BCEL", nor may "Apache" appear in their name, without
35   *    prior written permission of the Apache Software Foundation.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48   * SUCH DAMAGE.
49   * ====================================================================
50   *
51   * This software consists of voluntary contributions made by many
52   * individuals on behalf of the Apache Software Foundation.  For more
53   * information on the Apache Software Foundation, please see
54   * <http://www.apache.org/>.
55   */
56  
57  import org.apache.bcel.Constants;
58  import org.apache.bcel.classfile.*;
59  import java.util.ArrayList;
60  
61  /*** 
62   * Abstract super class for all possible java types, namely basic types
63   * such as int, object types like String and array types, e.g. int[]
64   *
65   * @version $Id: Type.java,v 1.8 2002/08/07 18:01:32 mdahm Exp $
66   * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
67   */
68  public abstract class Type implements java.io.Serializable {
69    protected byte   type;
70    protected String signature; // signature for the type
71  
72    /*** Predefined constants
73     */
74    public static final BasicType     VOID         = new BasicType(Constants.T_VOID);
75    public static final BasicType     BOOLEAN      = new BasicType(Constants.T_BOOLEAN);
76    public static final BasicType     INT          = new BasicType(Constants.T_INT);
77    public static final BasicType     SHORT        = new BasicType(Constants.T_SHORT);
78    public static final BasicType     BYTE         = new BasicType(Constants.T_BYTE);
79    public static final BasicType     LONG         = new BasicType(Constants.T_LONG);
80    public static final BasicType     DOUBLE       = new BasicType(Constants.T_DOUBLE);
81    public static final BasicType     FLOAT        = new BasicType(Constants.T_FLOAT);
82    public static final BasicType     CHAR         = new BasicType(Constants.T_CHAR);
83    public static final ObjectType    OBJECT       = new ObjectType("java.lang.Object");
84    public static final ObjectType    STRING       = new ObjectType("java.lang.String");
85    public static final ObjectType    STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
86    public static final ObjectType    THROWABLE    = new ObjectType("java.lang.Throwable");
87    public static final Type[]        NO_ARGS      = new Type[0];
88    public static final ReferenceType NULL         = new ReferenceType(){};
89    public static final Type          UNKNOWN      = new Type(Constants.T_UNKNOWN,
90  							    "<unknown object>"){};
91  
92    protected Type(byte t, String s) {
93      type      = t;
94      signature = s;
95    }
96  
97    /***
98     * @return signature for given type.
99     */
100   public String getSignature() { return signature; }
101 
102   /***
103    * @return type as defined in Constants
104    */
105   public byte getType() { return type; }
106 
107   /***
108    * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
109    */
110   public int getSize() {
111     switch(type) {
112     case Constants.T_DOUBLE:
113     case Constants.T_LONG: return 2;
114     case Constants.T_VOID: return 0;
115     default:     return 1;
116     }
117   }
118 
119   /***
120    * @return Type string, e.g. `int[]'
121    */
122   public String toString() {
123     return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN)))? signature :
124       Utility.signatureToString(signature, false);
125   }
126 
127   /***
128    * Convert type to Java method signature, e.g. int[] f(java.lang.String x)
129    * becomes (Ljava/lang/String;)[I
130    *
131    * @param return_type what the method returns
132    * @param arg_types what are the argument types
133    * @return method signature for given type(s).
134    */
135   public static String getMethodSignature(Type return_type, Type[] arg_types) { 
136     StringBuffer buf = new StringBuffer("(");
137     int length = (arg_types == null)? 0 : arg_types.length;
138 
139     for(int i=0; i < length; i++)
140       buf.append(arg_types[i].getSignature());
141 
142     buf.append(')');
143     buf.append(return_type.getSignature());
144 
145     return buf.toString();
146   }
147 
148   private static int consumed_chars=0; // Remember position in string, see getArgumentTypes
149 
150   /***
151    * Convert signature to a Type object.
152    * @param signature signature string such as Ljava/lang/String;
153    * @return type object
154    */
155   public static final Type getType(String signature)
156     throws StringIndexOutOfBoundsException
157   {
158     byte type = Utility.typeOfSignature(signature);
159 
160     if(type <= Constants.T_VOID) {
161       consumed_chars = 1;
162       return BasicType.getType(type);
163     } else if(type == Constants.T_ARRAY) {
164       int dim=0;
165       do { // Count dimensions
166 	dim++;
167       } while(signature.charAt(dim) == '[');
168 
169       // Recurse, but just once, if the signature is ok
170       Type t = getType(signature.substring(dim));
171 
172       consumed_chars += dim; // update counter
173 
174       return new ArrayType(t, dim);
175     } else { // type == T_REFERENCE
176       int index = signature.indexOf(';'); // Look for closing `;'
177 
178       if(index < 0)
179 	throw new ClassFormatException("Invalid signature: " + signature);
180 	
181       consumed_chars = index + 1; // "Lblabla;" `L' and `;' are removed
182 
183       return new ObjectType(signature.substring(1, index).replace('/', '.'));
184     }
185   }
186 
187   /***
188    * Convert return value of a method (signature) to a Type object.
189    *
190    * @param signature signature string such as (Ljava/lang/String;)V
191    * @return return type
192    */
193   public static Type getReturnType(String signature) {
194     try {
195       // Read return type after `)'
196       int index = signature.lastIndexOf(')') + 1;
197       return getType(signature.substring(index));
198     } catch(StringIndexOutOfBoundsException e) { // Should never occur
199       throw new ClassFormatException("Invalid method signature: " + signature);
200     }
201   }
202 
203   /***
204    * Convert arguments of a method (signature) to an array of Type objects.
205    * @param signature signature string such as (Ljava/lang/String;)V
206    * @return array of argument types
207    */
208   public static Type[] getArgumentTypes(String signature) {
209     ArrayList vec = new ArrayList();
210     int       index;
211     Type[]     types;
212 
213     try { // Read all declarations between for `(' and `)'
214       if(signature.charAt(0) != '(')
215 	throw new ClassFormatException("Invalid method signature: " + signature);
216 
217       index = 1; // current string position
218 
219       while(signature.charAt(index) != ')') {
220 	vec.add(getType(signature.substring(index)));
221 	index += consumed_chars; // update position
222       }
223     } catch(StringIndexOutOfBoundsException e) { // Should never occur
224       throw new ClassFormatException("Invalid method signature: " + signature);
225     }
226 	
227     types = new Type[vec.size()];
228     vec.toArray(types);
229     return types;
230   }
231 
232   /*** Convert runtime java.lang.Class to BCEL Type object.
233    * @param cl Java class
234    * @return corresponding Type object
235    */
236   public static Type getType(java.lang.Class cl) {
237     if(cl == null) {
238       throw new IllegalArgumentException("Class must not be null");
239     }
240 
241     /* That's an amzingly easy case, because getName() returns
242      * the signature. That's what we would have liked anyway.
243      */
244     if(cl.isArray()) {
245       return getType(cl.getName());
246     } else if(cl.isPrimitive()) {
247       if(cl == Integer.TYPE) {
248 	return INT;
249       } else if(cl == Void.TYPE) {
250 	return VOID;
251       } else if(cl == Double.TYPE) {
252 	return DOUBLE;
253       } else if(cl == Float.TYPE) {
254 	return FLOAT;
255       } else if(cl == Boolean.TYPE) {
256 	return BOOLEAN;
257       } else if(cl == Byte.TYPE) {
258 	return BYTE;
259       } else if(cl == Short.TYPE) {
260 	return SHORT;
261       } else if(cl == Byte.TYPE) {
262 	return BYTE;
263       } else if(cl == Long.TYPE) {
264 	return LONG;
265       } else if(cl == Character.TYPE) {
266 	return CHAR;
267       } else {
268 	throw new IllegalStateException("Ooops, what primitive type is " + cl);
269       }
270     } else { // "Real" class
271       return new ObjectType(cl.getName());
272     }
273   }
274 
275   public static String getSignature(java.lang.reflect.Method meth) {
276     StringBuffer sb = new StringBuffer("(");
277     Class[] params = meth.getParameterTypes(); // avoid clone
278 
279     for(int j = 0; j < params.length; j++) {
280       sb.append(getType(params[j]).getSignature());
281     }
282 
283     sb.append(")");
284     sb.append(getType(meth.getReturnType()).getSignature());
285     return sb.toString();
286   }
287 }
This page was automatically generated by Maven