blob: ded95b8662b09894a9e543c0c1ebc537d6cd645f [file] [log] [blame]
/*
* 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();
}
}