< prev index next >

src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java

Print this page

        

*** 1,8 **** /* ! * reserved comment block ! * DO NOT REMOVE OR ALTER! */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. --- 1,7 ---- /* ! * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership.
*** 16,254 **** * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ - package com.sun.org.apache.bcel.internal.generic; - - import com.sun.org.apache.bcel.internal.Constants; - import com.sun.org.apache.bcel.internal.classfile.*; 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[] * ! * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> */ ! public abstract class Type implements java.io.Serializable { ! 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, ! "<unknown object>"){}; ! 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 ClassFormatException("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 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 */ ! 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 ClassFormatException("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 ClassFormatException("Invalid method signature: " + signature); } - types = new Type[vec.size()]; vec.toArray(types); return types; } ! /** 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 amzingly 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(); } } --- 15,390 ---- * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sun.org.apache.bcel.internal.generic; import java.util.ArrayList; + import java.util.List; + + import com.sun.org.apache.bcel.internal.Const; + import com.sun.org.apache.bcel.internal.classfile.ClassFormatException; + import com.sun.org.apache.bcel.internal.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 1749603 2016-06-21 20:50:19Z ggregory $ ! */ ! public abstract class Type { ! ! private final byte type; ! private String signature; // signature for the type ! /** ! * Predefined constants */ ! public static final BasicType VOID = new BasicType(Const.T_VOID); ! public static final BasicType BOOLEAN = new BasicType(Const.T_BOOLEAN); ! public static final BasicType INT = new BasicType(Const.T_INT); ! public static final BasicType SHORT = new BasicType(Const.T_SHORT); ! public static final BasicType BYTE = new BasicType(Const.T_BYTE); ! public static final BasicType LONG = new BasicType(Const.T_LONG); ! public static final BasicType DOUBLE = new BasicType(Const.T_DOUBLE); ! public static final BasicType FLOAT = new BasicType(Const.T_FLOAT); ! public static final BasicType CHAR = new BasicType(Const.T_CHAR); public static final ObjectType OBJECT = new ObjectType("java.lang.Object"); + public static final ObjectType CLASS = new ObjectType("java.lang.Class"); 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]; // EMPTY, so immutable ! public static final ReferenceType NULL = new ReferenceType() { ! }; ! public static final Type UNKNOWN = new Type(Const.T_UNKNOWN, "<unknown object>") { ! }; ! protected Type(final byte t, final String s) { type = t; signature = s; } /** + * @return hashcode of Type + */ + @Override + public int hashCode() { + return type ^ signature.hashCode(); + } + + /** + * @return whether the Types are equal + */ + @Override + public boolean equals(final Object o) { + if (o instanceof Type) { + final Type t = (Type) o; + return (type == t.type) && signature.equals(t.signature); + } + return false; + } + + /** * @return signature for given type. */ ! public String getSignature() { ! return signature; ! } /** * @return type as defined in Constants */ ! public byte getType() { ! return type; ! } /** ! * boolean, short and char variable are considered as int in the stack or ! * local variable area. Returns {@link Type#INT} for ! * {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise ! * returns the given type. ! * ! * @since 6.0 ! */ ! public Type normalizeForStackOrLocal() { ! if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) { ! return Type.INT; ! } ! return this; ! } ! ! /** ! * @return stack size of this type (2 for long and double, 0 for void, 1 ! * otherwise) */ public int getSize() { ! switch (type) { ! case Const.T_DOUBLE: ! case Const.T_LONG: ! return 2; ! case Const.T_VOID: ! return 0; ! default: ! return 1; } } /** * @return Type string, e.g. `int[]' */ + @Override public String toString() { ! return ((this.equals(Type.NULL) || (type >= Const.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(final Type return_type, final Type[] arg_types) { ! final StringBuilder buf = new StringBuilder("("); ! if (arg_types != null) { ! for (final Type arg_type : arg_types) { ! buf.append(arg_type.getSignature()); ! } ! } buf.append(')'); buf.append(return_type.getSignature()); return buf.toString(); } ! private static final ThreadLocal<Integer> consumed_chars = new ThreadLocal<Integer>() { ! ! @Override ! protected Integer initialValue() { ! return Integer.valueOf(0); ! } ! };//int consumed_chars=0; // Remember position in string, see getArgumentTypes ! ! private static int unwrap(final ThreadLocal<Integer> tl) { ! return tl.get().intValue(); ! } ! ! private static void wrap(final ThreadLocal<Integer> tl, final int value) { ! tl.set(Integer.valueOf(value)); ! } /** * Convert signature to a Type object. + * * @param signature signature string such as Ljava/lang/String; * @return type object */ ! // @since 6.0 no longer final ! public static Type getType(final String signature) throws StringIndexOutOfBoundsException { ! final byte type = Utility.typeOfSignature(signature); ! if (type <= Const.T_VOID) { ! //corrected concurrent private static field acess ! wrap(consumed_chars, 1); return BasicType.getType(type); ! } else if (type == Const.T_ARRAY) { ! int dim = 0; do { // Count dimensions dim++; ! } while (signature.charAt(dim) == '['); // Recurse, but just once, if the signature is ok ! final Type t = getType(signature.substring(dim)); ! //corrected concurrent private static field acess ! // consumed_chars += dim; // update counter - is replaced by ! final int _temp = unwrap(consumed_chars) + dim; ! wrap(consumed_chars, _temp); return new ArrayType(t, dim); } else { // type == T_REFERENCE ! // Utility.signatureToString understands how to parse ! // generic types. ! final String parsedSignature = Utility.signatureToString(signature, false); ! wrap(consumed_chars, parsedSignature.length() + 2); // "Lblabla;" `L' and `;' are removed ! return ObjectType.getInstance(parsedSignature.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(final String signature) { try { // Read return type after `)' ! final int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); ! } catch (final StringIndexOutOfBoundsException e) { // Should never occur ! throw new ClassFormatException("Invalid method signature: " + signature, e); } } /** * 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(final String signature) { ! final List<Type> vec = new ArrayList<>(); 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) != ')') { vec.add(getType(signature.substring(index))); ! //corrected concurrent private static field acess ! index += unwrap(consumed_chars); // update position } ! } catch (final StringIndexOutOfBoundsException e) { // Should never occur ! throw new ClassFormatException("Invalid method signature: " + signature, e); } types = new Type[vec.size()]; vec.toArray(types); return types; } ! /** ! * Convert runtime java.lang.Class to BCEL Type object. ! * * @param cl Java class * @return corresponding Type object */ ! public static Type getType(final java.lang.Class<?> cl) { ! if (cl == null) { throw new IllegalArgumentException("Class must not be null"); } /* That's an amzingly 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 ObjectType.getInstance(cl.getName()); } } ! /** ! * Convert runtime java.lang.Class[] to BCEL Type objects. ! * ! * @param classes an array of runtime class objects ! * @return array of corresponding Type objects ! */ ! public static Type[] getTypes(final java.lang.Class<?>[] classes) { ! final Type[] ret = new Type[classes.length]; ! for (int i = 0; i < ret.length; i++) { ! ret[i] = getType(classes[i]); ! } ! return ret; ! } ! ! public static String getSignature(final java.lang.reflect.Method meth) { ! final StringBuilder sb = new StringBuilder("("); ! final Class<?>[] params = meth.getParameterTypes(); // avoid clone ! for (final Class<?> param : params) { ! sb.append(getType(param).getSignature()); } sb.append(")"); sb.append(getType(meth.getReturnType()).getSignature()); return sb.toString(); } + + static int size(final int coded) { + return coded & 3; + } + + static int consumed(final int coded) { + return coded >> 2; + } + + static int encode(final int size, final int consumed) { + return consumed << 2 | size; + } + + static int getArgumentTypesSize(final String signature) { + int res = 0; + int index; + 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) != ')') { + final int coded = getTypeSize(signature.substring(index)); + res += size(coded); + index += consumed(coded); + } + } catch (final StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + return res; + } + + static int getTypeSize(final String signature) throws StringIndexOutOfBoundsException { + final byte type = Utility.typeOfSignature(signature); + if (type <= Const.T_VOID) { + return encode(BasicType.getType(type).getSize(), 1); + } else if (type == Const.T_ARRAY) { + int dim = 0; + do { // Count dimensions + dim++; + } while (signature.charAt(dim) == '['); + // Recurse, but just once, if the signature is ok + final int consumed = consumed(getTypeSize(signature.substring(dim))); + return encode(1, dim + consumed); + } else { // type == T_REFERENCE + final int index = signature.indexOf(';'); // Look for closing `;' + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + return encode(1, index + 1); + } + } + + static int getReturnTypeSize(final String signature) { + final int index = signature.lastIndexOf(')') + 1; + return Type.size(getTypeSize(signature.substring(index))); + } + + + /* + * Currently only used by the ArrayType constructor. + * The signature has a complicated dependency on other parameter + * so it's tricky to do it in a call to the super ctor. + */ + void setSignature(final String signature) { + this.signature = signature; + } }
< prev index next >