| /* |
| * Copyright 2003,2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * 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 org.mockito.cglib.core; |
| |
| import java.util.*; |
| |
| import org.mockito.asm.Type; |
| |
| public class TypeUtils { |
| private static final Map transforms = new HashMap(); |
| private static final Map rtransforms = new HashMap(); |
| |
| private TypeUtils() { |
| } |
| |
| static { |
| transforms.put("void", "V"); |
| transforms.put("byte", "B"); |
| transforms.put("char", "C"); |
| transforms.put("double", "D"); |
| transforms.put("float", "F"); |
| transforms.put("int", "I"); |
| transforms.put("long", "J"); |
| transforms.put("short", "S"); |
| transforms.put("boolean", "Z"); |
| |
| CollectionUtils.reverse(transforms, rtransforms); |
| } |
| |
| public static Type getType(String className) { |
| return Type.getType("L" + className.replace('.', '/') + ";"); |
| } |
| |
| public static boolean isFinal(int access) { |
| return (Constants.ACC_FINAL & access) != 0; |
| } |
| |
| public static boolean isStatic(int access) { |
| return (Constants.ACC_STATIC & access) != 0; |
| } |
| |
| public static boolean isProtected(int access) { |
| return (Constants.ACC_PROTECTED & access) != 0; |
| } |
| |
| public static boolean isPublic(int access) { |
| return (Constants.ACC_PUBLIC & access) != 0; |
| } |
| |
| public static boolean isAbstract(int access) { |
| return (Constants.ACC_ABSTRACT & access) != 0; |
| } |
| |
| public static boolean isInterface(int access) { |
| return (Constants.ACC_INTERFACE & access) != 0; |
| } |
| |
| public static boolean isPrivate(int access) { |
| return (Constants.ACC_PRIVATE & access) != 0; |
| } |
| |
| public static boolean isSynthetic(int access) { |
| return (Constants.ACC_SYNTHETIC & access) != 0; |
| } |
| |
| // getPackage returns null on JDK 1.2 |
| public static String getPackageName(Type type) { |
| return getPackageName(getClassName(type)); |
| } |
| |
| public static String getPackageName(String className) { |
| int idx = className.lastIndexOf('.'); |
| return (idx < 0) ? "" : className.substring(0, idx); |
| } |
| |
| public static String upperFirst(String s) { |
| if (s == null || s.length() == 0) { |
| return s; |
| } |
| return Character.toUpperCase(s.charAt(0)) + s.substring(1); |
| } |
| |
| public static String getClassName(Type type) { |
| if (isPrimitive(type)) { |
| return (String)rtransforms.get(type.getDescriptor()); |
| } else if (isArray(type)) { |
| return getClassName(getComponentType(type)) + "[]"; |
| } else { |
| return type.getClassName(); |
| } |
| } |
| |
| public static Type[] add(Type[] types, Type extra) { |
| if (types == null) { |
| return new Type[]{ extra }; |
| } else { |
| List list = Arrays.asList(types); |
| if (list.contains(extra)) { |
| return types; |
| } |
| Type[] copy = new Type[types.length + 1]; |
| System.arraycopy(types, 0, copy, 0, types.length); |
| copy[types.length] = extra; |
| return copy; |
| } |
| } |
| |
| public static Type[] add(Type[] t1, Type[] t2) { |
| // TODO: set semantics? |
| Type[] all = new Type[t1.length + t2.length]; |
| System.arraycopy(t1, 0, all, 0, t1.length); |
| System.arraycopy(t2, 0, all, t1.length, t2.length); |
| return all; |
| } |
| |
| public static Type fromInternalName(String name) { |
| // TODO; primitives? |
| return Type.getType("L" + name + ";"); |
| } |
| |
| public static Type[] fromInternalNames(String[] names) { |
| if (names == null) { |
| return null; |
| } |
| Type[] types = new Type[names.length]; |
| for (int i = 0; i < names.length; i++) { |
| types[i] = fromInternalName(names[i]); |
| } |
| return types; |
| } |
| |
| public static int getStackSize(Type[] types) { |
| int size = 0; |
| for (int i = 0; i < types.length; i++) { |
| size += types[i].getSize(); |
| } |
| return size; |
| } |
| |
| public static String[] toInternalNames(Type[] types) { |
| if (types == null) { |
| return null; |
| } |
| String[] names = new String[types.length]; |
| for (int i = 0; i < types.length; i++) { |
| names[i] = types[i].getInternalName(); |
| } |
| return names; |
| } |
| |
| public static Signature parseSignature(String s) { |
| int space = s.indexOf(' '); |
| int lparen = s.indexOf('(', space); |
| int rparen = s.indexOf(')', lparen); |
| String returnType = s.substring(0, space); |
| String methodName = s.substring(space + 1, lparen); |
| StringBuffer sb = new StringBuffer(); |
| sb.append('('); |
| for (Iterator it = parseTypes(s, lparen + 1, rparen).iterator(); it.hasNext();) { |
| sb.append(it.next()); |
| } |
| sb.append(')'); |
| sb.append(map(returnType)); |
| return new Signature(methodName, sb.toString()); |
| } |
| |
| public static Type parseType(String s) { |
| return Type.getType(map(s)); |
| } |
| |
| public static Type[] parseTypes(String s) { |
| List names = parseTypes(s, 0, s.length()); |
| Type[] types = new Type[names.size()]; |
| for (int i = 0; i < types.length; i++) { |
| types[i] = Type.getType((String)names.get(i)); |
| } |
| return types; |
| } |
| |
| public static Signature parseConstructor(Type[] types) { |
| StringBuffer sb = new StringBuffer(); |
| sb.append("("); |
| for (int i = 0; i < types.length; i++) { |
| sb.append(types[i].getDescriptor()); |
| } |
| sb.append(")"); |
| sb.append("V"); |
| return new Signature(Constants.CONSTRUCTOR_NAME, sb.toString()); |
| } |
| |
| public static Signature parseConstructor(String sig) { |
| return parseSignature("void <init>(" + sig + ")"); // TODO |
| } |
| |
| private static List parseTypes(String s, int mark, int end) { |
| List types = new ArrayList(5); |
| for (;;) { |
| int next = s.indexOf(',', mark); |
| if (next < 0) { |
| break; |
| } |
| types.add(map(s.substring(mark, next).trim())); |
| mark = next + 1; |
| } |
| types.add(map(s.substring(mark, end).trim())); |
| return types; |
| } |
| |
| private static String map(String type) { |
| if (type.equals("")) { |
| return type; |
| } |
| String t = (String)transforms.get(type); |
| if (t != null) { |
| return t; |
| } else if (type.indexOf('.') < 0) { |
| return map("java.lang." + type); |
| } else { |
| StringBuffer sb = new StringBuffer(); |
| int index = 0; |
| while ((index = type.indexOf("[]", index) + 1) > 0) { |
| sb.append('['); |
| } |
| type = type.substring(0, type.length() - sb.length() * 2); |
| sb.append('L').append(type.replace('.', '/')).append(';'); |
| return sb.toString(); |
| } |
| } |
| |
| public static Type getBoxedType(Type type) { |
| switch (type.getSort()) { |
| case Type.CHAR: |
| return Constants.TYPE_CHARACTER; |
| case Type.BOOLEAN: |
| return Constants.TYPE_BOOLEAN; |
| case Type.DOUBLE: |
| return Constants.TYPE_DOUBLE; |
| case Type.FLOAT: |
| return Constants.TYPE_FLOAT; |
| case Type.LONG: |
| return Constants.TYPE_LONG; |
| case Type.INT: |
| return Constants.TYPE_INTEGER; |
| case Type.SHORT: |
| return Constants.TYPE_SHORT; |
| case Type.BYTE: |
| return Constants.TYPE_BYTE; |
| default: |
| return type; |
| } |
| } |
| |
| public static Type getUnboxedType(Type type) { |
| if (Constants.TYPE_INTEGER.equals(type)) { |
| return Type.INT_TYPE; |
| } else if (Constants.TYPE_BOOLEAN.equals(type)) { |
| return Type.BOOLEAN_TYPE; |
| } else if (Constants.TYPE_DOUBLE.equals(type)) { |
| return Type.DOUBLE_TYPE; |
| } else if (Constants.TYPE_LONG.equals(type)) { |
| return Type.LONG_TYPE; |
| } else if (Constants.TYPE_CHARACTER.equals(type)) { |
| return Type.CHAR_TYPE; |
| } else if (Constants.TYPE_BYTE.equals(type)) { |
| return Type.BYTE_TYPE; |
| } else if (Constants.TYPE_FLOAT.equals(type)) { |
| return Type.FLOAT_TYPE; |
| } else if (Constants.TYPE_SHORT.equals(type)) { |
| return Type.SHORT_TYPE; |
| } else { |
| return type; |
| } |
| } |
| |
| public static boolean isArray(Type type) { |
| return type.getSort() == Type.ARRAY; |
| } |
| |
| public static Type getComponentType(Type type) { |
| if (!isArray(type)) { |
| throw new IllegalArgumentException("Type " + type + " is not an array"); |
| } |
| return Type.getType(type.getDescriptor().substring(1)); |
| } |
| |
| public static boolean isPrimitive(Type type) { |
| switch (type.getSort()) { |
| case Type.ARRAY: |
| case Type.OBJECT: |
| return false; |
| default: |
| return true; |
| } |
| } |
| |
| public static String emulateClassGetName(Type type) { |
| if (isArray(type)) { |
| return type.getDescriptor().replace('/', '.'); |
| } else { |
| return getClassName(type); |
| } |
| } |
| |
| public static boolean isConstructor(MethodInfo method) { |
| return method.getSignature().getName().equals(Constants.CONSTRUCTOR_NAME); |
| } |
| |
| public static Type[] getTypes(Class[] classes) { |
| if (classes == null) { |
| return null; |
| } |
| Type[] types = new Type[classes.length]; |
| for (int i = 0; i < classes.length; i++) { |
| types[i] = Type.getType(classes[i]); |
| } |
| return types; |
| } |
| |
| public static int ICONST(int value) { |
| switch (value) { |
| case -1: return Constants.ICONST_M1; |
| case 0: return Constants.ICONST_0; |
| case 1: return Constants.ICONST_1; |
| case 2: return Constants.ICONST_2; |
| case 3: return Constants.ICONST_3; |
| case 4: return Constants.ICONST_4; |
| case 5: return Constants.ICONST_5; |
| } |
| return -1; // error |
| } |
| |
| public static int LCONST(long value) { |
| if (value == 0L) { |
| return Constants.LCONST_0; |
| } else if (value == 1L) { |
| return Constants.LCONST_1; |
| } else { |
| return -1; // error |
| } |
| } |
| |
| public static int FCONST(float value) { |
| if (value == 0f) { |
| return Constants.FCONST_0; |
| } else if (value == 1f) { |
| return Constants.FCONST_1; |
| } else if (value == 2f) { |
| return Constants.FCONST_2; |
| } else { |
| return -1; // error |
| } |
| } |
| |
| public static int DCONST(double value) { |
| if (value == 0d) { |
| return Constants.DCONST_0; |
| } else if (value == 1d) { |
| return Constants.DCONST_1; |
| } else { |
| return -1; // error |
| } |
| } |
| |
| public static int NEWARRAY(Type type) { |
| switch (type.getSort()) { |
| case Type.BYTE: |
| return Constants.T_BYTE; |
| case Type.CHAR: |
| return Constants.T_CHAR; |
| case Type.DOUBLE: |
| return Constants.T_DOUBLE; |
| case Type.FLOAT: |
| return Constants.T_FLOAT; |
| case Type.INT: |
| return Constants.T_INT; |
| case Type.LONG: |
| return Constants.T_LONG; |
| case Type.SHORT: |
| return Constants.T_SHORT; |
| case Type.BOOLEAN: |
| return Constants.T_BOOLEAN; |
| default: |
| return -1; // error |
| } |
| } |
| |
| public static String escapeType(String s) { |
| StringBuffer sb = new StringBuffer(); |
| for (int i = 0, len = s.length(); i < len; i++) { |
| char c = s.charAt(i); |
| switch (c) { |
| case '$': sb.append("$24"); break; |
| case '.': sb.append("$2E"); break; |
| case '[': sb.append("$5B"); break; |
| case ';': sb.append("$3B"); break; |
| case '(': sb.append("$28"); break; |
| case ')': sb.append("$29"); break; |
| case '/': sb.append("$2F"); break; |
| default: |
| sb.append(c); |
| } |
| } |
| return sb.toString(); |
| } |
| } |