package org.apache.bcel.generic; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache BCEL" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Apache BCEL", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ import org.apache.bcel.Constants; import org.apache.bcel.classfile.*; import java.io.*; import java.util.ArrayList; /** * Abstract super class for all possible java types, namely basic types * such as int, object types like String and array types, e.g. int[] * * @version $Id$ * @author M. Dahm */ public abstract class Type { protected byte type; protected String signature; // signature for the type /** Predefined constants */ public static final BasicType VOID = new BasicType(Constants.T_VOID); public static final BasicType BOOLEAN = new BasicType(Constants.T_BOOLEAN); public static final BasicType INT = new BasicType(Constants.T_INT); public static final BasicType SHORT = new BasicType(Constants.T_SHORT); public static final BasicType BYTE = new BasicType(Constants.T_BYTE); public static final BasicType LONG = new BasicType(Constants.T_LONG); public static final BasicType DOUBLE = new BasicType(Constants.T_DOUBLE); public static final BasicType FLOAT = new BasicType(Constants.T_FLOAT); public static final BasicType CHAR = new BasicType(Constants.T_CHAR); public static final ObjectType OBJECT = new ObjectType("java.lang.Object"); public static final ObjectType STRING = new ObjectType("java.lang.String"); public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer"); public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable"); public static final Type[] NO_ARGS = new Type[0]; public static final ReferenceType NULL = new ReferenceType(); public static final Type UNKNOWN = new Type(Constants.T_UNKNOWN, ""){}; protected Type(byte t, String s) { type = t; signature = s; } /** * @return signature for given type. */ public String getSignature() { return signature; } /** * @return type as defined in Constants */ public byte getType() { return type; } /** * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise) */ public int getSize() { switch(type) { case Constants.T_DOUBLE: case Constants.T_LONG: return 2; case Constants.T_VOID: return 0; default: return 1; } } /** * @return Type string, e.g. `int[]' */ public String toString() { return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN)))? signature : Utility.signatureToString(signature, false); } /** * Convert type to Java method signature, e.g. int[] f(java.lang.String x) * becomes (Ljava/lang/String;)[I * * @param return_type what the method returns * @param arg_types what are the argument types * @return method signature for given type(s). */ public static String getMethodSignature(Type return_type, Type[] arg_types) { StringBuffer buf = new StringBuffer("("); int length = (arg_types == null)? 0 : arg_types.length; for(int i=0; i < length; i++) buf.append(arg_types[i].getSignature()); buf.append(')'); buf.append(return_type.getSignature()); return buf.toString(); } private static int consumed_chars=0; // Remember position in string, see getArgumentTypes /** * Convert signature to a Type object. * @param signature signature string such as Ljava/lang/String; * @return type object */ public static final Type getType(String signature) throws StringIndexOutOfBoundsException { byte type = Utility.typeOfSignature(signature); if(type <= Constants.T_VOID) { consumed_chars = 1; return BasicType.getType(type); } else if(type == Constants.T_ARRAY) { int dim=0; do { // Count dimensions dim++; } while(signature.charAt(dim) == '['); // Recurse, but just once, if the signature is ok Type t = getType(signature.substring(dim)); consumed_chars += dim; // update counter return new ArrayType(t, dim); } else { // type == T_REFERENCE int index = signature.indexOf(';'); // Look for closing `;' if(index < 0) throw new ClassFormatError("Invalid signature: " + signature); consumed_chars = index + 1; // "Lblabla;" `L' and `;' are removed return new ObjectType(signature.substring(1, index).replace('/', '.')); } } /** * Convert return value of a method (signature) to a Type object. * * @param signature signature string such as (Ljava/lang/String;)V * @return return type */ public static Type getReturnType(String signature) { try { // Read return type after `)' int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatError("Invalid method signature: " + signature); } } /** * Convert arguments of a method (signature) to an array of Type objects. * @param signature signature string such as (Ljava/lang/String;)V * @return array of argument types */ public static Type[] getArgumentTypes(String signature) { ArrayList vec = new ArrayList(); int index; Type[] types; try { // Read all declarations between for `(' and `)' if(signature.charAt(0) != '(') throw new ClassFormatError("Invalid method signature: " + signature); index = 1; // current string position while(signature.charAt(index) != ')') { vec.add(getType(signature.substring(index))); index += consumed_chars; // update position } } catch(StringIndexOutOfBoundsException e) { // Should never occur throw new ClassFormatError("Invalid method signature: " + signature); } types = new Type[vec.size()]; vec.toArray(types); return types; } }