123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- package org.aspectj.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
- * <http://www.apache.org/>.
- */
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- import org.aspectj.apache.bcel.Constants;
- import org.aspectj.apache.bcel.ConstantsInitializer;
- import org.aspectj.apache.bcel.classfile.ClassFormatException;
- import org.aspectj.apache.bcel.classfile.Utility;
-
- /**
- * 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: Type.java,v 1.14 2011/09/28 01:14:54 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- *
- * modified: AndyClement 2-mar-05: Removed unnecessary static and optimized
- */
- public abstract class Type {
- protected byte type;
- protected String signature;
-
- /* 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 OBJECT_ARRAY = new ObjectType("java.lang.Object[]");
- public static final ObjectType STRING_ARRAY = new ObjectType("java.lang.String[]");
- public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
- public static final ObjectType STRINGBUILDER = new ObjectType("java.lang.StringBuilder");
- public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable");
- public static final ObjectType CLASS = new ObjectType("java.lang.Class");
- public static final ObjectType INTEGER = new ObjectType("java.lang.Integer");
- public static final ObjectType EXCEPTION = new ObjectType("java.lang.Exception");
- public static final ObjectType LIST = new ObjectType("java.util.List");
- public static final ObjectType ITERATOR = new ObjectType("java.util.Iterator");
- 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, "<unknown object>") {
- };
- public static final Type[] STRINGARRAY1 = new Type[] { STRING };
- public static final Type[] STRINGARRAY2 = new Type[] { STRING, STRING };
- public static final Type[] STRINGARRAY3 = new Type[] { STRING, STRING, STRING };
- public static final Type[] STRINGARRAY4 = new Type[] { STRING, STRING, STRING, STRING };
- public static final Type[] STRINGARRAY5 = new Type[] { STRING, STRING, STRING, STRING, STRING };
- public static final Type[] STRINGARRAY6 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING };
- public static final Type[] STRINGARRAY7 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING, STRING };
-
- private static Map<String, Type> commonTypes = new HashMap<String, Type>();
-
- static {
- commonTypes.put(STRING.getSignature(), STRING);
- commonTypes.put(THROWABLE.getSignature(), THROWABLE);
- commonTypes.put(VOID.getSignature(), VOID);
- commonTypes.put(BOOLEAN.getSignature(), BOOLEAN);
- commonTypes.put(BYTE.getSignature(), BYTE);
- commonTypes.put(SHORT.getSignature(), SHORT);
- commonTypes.put(CHAR.getSignature(), CHAR);
- commonTypes.put(INT.getSignature(), INT);
- commonTypes.put(LONG.getSignature(), LONG);
- commonTypes.put(DOUBLE.getSignature(), DOUBLE);
- commonTypes.put(FLOAT.getSignature(), FLOAT);
- commonTypes.put(CLASS.getSignature(), CLASS);
- commonTypes.put(OBJECT.getSignature(), OBJECT);
- commonTypes.put(STRING_ARRAY.getSignature(), STRING_ARRAY);
- commonTypes.put(OBJECT_ARRAY.getSignature(), OBJECT_ARRAY);
- commonTypes.put(INTEGER.getSignature(), INTEGER);
- commonTypes.put(EXCEPTION.getSignature(), EXCEPTION);
- commonTypes.put(STRINGBUFFER.getSignature(), STRINGBUFFER);
- commonTypes.put(STRINGBUILDER.getSignature(), STRINGBUILDER);
- commonTypes.put(LIST.getSignature(), LIST);
- commonTypes.put(ITERATOR.getSignature(), ITERATOR);
- ConstantsInitializer.initialize(); // needs calling because it will not have run properly the first time
- }
-
- protected Type(byte t, String s) {
- type = t;
- signature = s;
- }
-
- public String getSignature() {
- return signature;
- }
-
- 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[]'
- */
- @Override
- public String toString() {
- return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN))) ? signature : Utility
- .signatureToString(signature, false);
- }
-
- public static final Type getType(String signature) {
- Type t = commonTypes.get(signature);
- if (t != null) {
- return t;
- }
- byte type = Utility.typeOfSignature(signature);
- if (type <= Constants.T_VOID) {
- return BasicType.getType(type);
- } else if (type == Constants.T_ARRAY) {
- int dim = 0;
- do {
- dim++;
- } while (signature.charAt(dim) == '[');
- // Recurse, but just once, if the signature is ok
- Type componentType = getType(signature.substring(dim));
- return new ArrayType(componentType, dim);
- } else { // type == T_REFERENCE
- // generics awareness
- int nextAngly = signature.indexOf('<');
- // Format is 'Lblahblah;'
- int index = signature.indexOf(';'); // Look for closing ';'
-
- String typeString = null;
- if (nextAngly == -1 || nextAngly > index) {
- typeString = signature.substring(1, index).replace('/', '.');
- } else {
- boolean endOfSigReached = false;
- int posn = nextAngly;
- int genericDepth = 0;
- while (!endOfSigReached) {
- switch (signature.charAt(posn++)) {
- case '<':
- genericDepth++;
- break;
- case '>':
- genericDepth--;
- break;
- case ';':
- if (genericDepth == 0) {
- endOfSigReached = true;
- }
- break;
- default:
- }
- }
- index = posn - 1;
- typeString = signature.substring(1, nextAngly).replace('/', '.');
- }
- // ObjectType doesn't currently store parameterized info
- return new ObjectType(typeString);
- }
- }
-
- /**
- * Convert signature to a Type object.
- *
- * @param signature signature string such as Ljava/lang/String;
- * @return type object
- */
- public static final TypeHolder getTypeInternal(String signature) throws StringIndexOutOfBoundsException {
- byte type = Utility.typeOfSignature(signature);
-
- if (type <= Constants.T_VOID) {
- return new TypeHolder(BasicType.getType(type), 1);
- } else if (type == Constants.T_ARRAY) {
- int dim = 0;
- do {
- dim++;
- } while (signature.charAt(dim) == '[');
- // Recurse, but just once, if the signature is ok
- TypeHolder th = getTypeInternal(signature.substring(dim));
- return new TypeHolder(new ArrayType(th.getType(), dim), dim + th.getConsumed());
- } else { // type == T_REFERENCE
- // Format is 'Lblahblah;'
- int index = signature.indexOf(';'); // Look for closing ';'
- if (index < 0) {
- throw new ClassFormatException("Invalid signature: " + signature);
- }
-
- // generics awareness
- int nextAngly = signature.indexOf('<');
- String typeString = null;
- if (nextAngly == -1 || nextAngly > index) {
- typeString = signature.substring(1, index).replace('/', '.');
- } else {
- boolean endOfSigReached = false;
- int posn = nextAngly;
- int genericDepth = 0;
- while (!endOfSigReached) {
- switch (signature.charAt(posn++)) {
- case '<':
- genericDepth++;
- break;
- case '>':
- genericDepth--;
- break;
- case ';':
- if (genericDepth == 0) {
- endOfSigReached = true;
- }
- break;
- default:
- }
- }
- index = posn - 1;
- typeString = signature.substring(1, nextAngly).replace('/', '.');
- }
- // ObjectType doesn't currently store parameterized info
- return new TypeHolder(new ObjectType(typeString), index + 1);
- }
- }
-
- /**
- * 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 ClassFormatException("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
- */
- // OPTIMIZE crap impl
- public static Type[] getArgumentTypes(String signature) {
- List<Type> argumentTypes = new ArrayList<Type>();
- int index;
- Type[] types;
-
- try { // Read all declarations between for `(' and `)'
- if (signature.charAt(0) != '(') {
- throw new ClassFormatException("Invalid method signature: " + signature);
- }
-
- index = 1; // current string position
-
- while (signature.charAt(index) != ')') {
- TypeHolder th = getTypeInternal(signature.substring(index));
- argumentTypes.add(th.getType());
- index += th.getConsumed(); // update position
- }
- } catch (StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature);
- }
-
- types = new Type[argumentTypes.size()];
- argumentTypes.toArray(types);
- return types;
- }
-
- /**
- * Work out the type of each argument in the signature and return the cumulative sizes of all the types (size means number of
- * stack slots it consumes, eg double=2, int=1). Unlike the call above, this does minimal unpacking
- */
- public static int getArgumentSizes(String signature) {
- int size = 0;
- if (signature.charAt(0) != '(') {
- throw new ClassFormatException("Invalid method signature: " + signature);
- }
-
- int index = 1; // current string position
- try {
- while (signature.charAt(index) != ')') {
- byte type = Utility.typeOfSignature(signature.charAt(index));
- if (type <= Constants.T_VOID) {
- size += BasicType.getType(type).getSize();
- index++;
- } else if (type == Constants.T_ARRAY) {
- int dim = 0;
- do {
- dim++;
- } while (signature.charAt(dim + index) == '[');
- TypeHolder th = getTypeInternal(signature.substring(dim + index));
- size += 1;
- index += dim + th.getConsumed();
- } else { // type == T_REFERENCE
- // Format is 'Lblahblah;'
- int index2 = signature.indexOf(';', index); // Look for closing ';'
-
- // generics awareness
- int nextAngly = signature.indexOf('<', index);
- if (nextAngly == -1 || nextAngly > index2) {
- } else {
- boolean endOfSigReached = false;
- int posn = nextAngly;
- int genericDepth = 0;
- while (!endOfSigReached) {
- switch (signature.charAt(posn++)) {
- case '<':
- genericDepth++;
- break;
- case '>':
- genericDepth--;
- break;
- case ';':
- if (genericDepth == 0) {
- endOfSigReached = true;
- }
- break;
- default:
- }
- }
- index2 = posn - 1;
- }
- size++;
- index = index2 + 1;
- }
- }
- } catch (StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature);
- }
- return size;
- }
-
- /**
- * Return the size of the type expressed in the signature. The signature should contain only one type.
- */
- public static int getTypeSize(String signature) {
- byte type = Utility.typeOfSignature(signature.charAt(0));
- if (type <= Constants.T_VOID) {
- return BasicType.getType(type).getSize();
- } else if (type == Constants.T_ARRAY) {
- return 1;
- } else { // type == T_REFERENCE
- return 1;
- }
- }
-
- /**
- * Convert runtime java.lang.Class to BCEL Type object.
- *
- * @param cl Java class
- * @return corresponding Type object
- */
- public static Type getType(java.lang.Class cl) {
- if (cl == null) {
- throw new IllegalArgumentException("Class must not be null");
- }
-
- /*
- * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway.
- */
- if (cl.isArray()) {
- return getType(cl.getName());
- } else if (cl.isPrimitive()) {
- if (cl == Integer.TYPE) {
- return INT;
- } else if (cl == Void.TYPE) {
- return VOID;
- } else if (cl == Double.TYPE) {
- return DOUBLE;
- } else if (cl == Float.TYPE) {
- return FLOAT;
- } else if (cl == Boolean.TYPE) {
- return BOOLEAN;
- } else if (cl == Byte.TYPE) {
- return BYTE;
- } else if (cl == Short.TYPE) {
- return SHORT;
- } else if (cl == Byte.TYPE) {
- return BYTE;
- } else if (cl == Long.TYPE) {
- return LONG;
- } else if (cl == Character.TYPE) {
- return CHAR;
- } else {
- throw new IllegalStateException("Ooops, what primitive type is " + cl);
- }
- } else { // "Real" class
- return new ObjectType(cl.getName());
- }
- }
-
- public static String getSignature(java.lang.reflect.Method meth) {
- StringBuffer sb = new StringBuffer("(");
- Class[] params = meth.getParameterTypes(); // avoid clone
-
- for (int j = 0; j < params.length; j++) {
- sb.append(getType(params[j]).getSignature());
- }
-
- sb.append(")");
- sb.append(getType(meth.getReturnType()).getSignature());
- return sb.toString();
- }
-
- public static String getSignature(java.lang.reflect.Constructor<?> cons) {
- StringBuffer sb = new StringBuffer("(");
- Class<?>[] params = cons.getParameterTypes(); // avoid clone
-
- for (int j = 0; j < params.length; j++) {
- sb.append(getType(params[j]).getSignature());
- }
-
- sb.append(")V");
- return sb.toString();
- }
-
- public static class TypeHolder {
- private Type t;
- private int consumed;
-
- public Type getType() {
- return t;
- }
-
- public int getConsumed() {
- return consumed;
- }
-
- public TypeHolder(Type t, int i) {
- this.t = t;
- this.consumed = i;
- }
- }
-
- }
|