--- old/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java 2017-08-08 16:06:08.860185418 -0700
+++ new/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java 2017-08-08 16:06:08.772181012 -0700
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -18,237 +17,374 @@
* 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;
+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[]
+ * 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 M. Dahm
+ * @version $Id: Type.java 1749603 2016-06-21 20:50:19Z ggregory $
*/
-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,
- ""){};
-
- 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();
- }
+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, "") {
+ };
+
+ 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 consumed_chars = new ThreadLocal() {
+
+ @Override
+ protected Integer initialValue() {
+ return Integer.valueOf(0);
+ }
+ };//int consumed_chars=0; // Remember position in string, see getArgumentTypes
+
+ private static int unwrap(final ThreadLocal tl) {
+ return tl.get().intValue();
+ }
+
+ private static void wrap(final ThreadLocal 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 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;
+ }
}