TypeUtils.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/* 2 * Copyright 2003,2004 The Apache Software Foundation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package org.mockito.cglib.core; 17 18import java.util.*; 19 20import org.mockito.asm.Type; 21 22public class TypeUtils { 23 private static final Map transforms = new HashMap(); 24 private static final Map rtransforms = new HashMap(); 25 26 private TypeUtils() { 27 } 28 29 static { 30 transforms.put("void", "V"); 31 transforms.put("byte", "B"); 32 transforms.put("char", "C"); 33 transforms.put("double", "D"); 34 transforms.put("float", "F"); 35 transforms.put("int", "I"); 36 transforms.put("long", "J"); 37 transforms.put("short", "S"); 38 transforms.put("boolean", "Z"); 39 40 CollectionUtils.reverse(transforms, rtransforms); 41 } 42 43 public static Type getType(String className) { 44 return Type.getType("L" + className.replace('.', '/') + ";"); 45 } 46 47 public static boolean isFinal(int access) { 48 return (Constants.ACC_FINAL & access) != 0; 49 } 50 51 public static boolean isStatic(int access) { 52 return (Constants.ACC_STATIC & access) != 0; 53 } 54 55 public static boolean isProtected(int access) { 56 return (Constants.ACC_PROTECTED & access) != 0; 57 } 58 59 public static boolean isPublic(int access) { 60 return (Constants.ACC_PUBLIC & access) != 0; 61 } 62 63 public static boolean isAbstract(int access) { 64 return (Constants.ACC_ABSTRACT & access) != 0; 65 } 66 67 public static boolean isInterface(int access) { 68 return (Constants.ACC_INTERFACE & access) != 0; 69 } 70 71 public static boolean isPrivate(int access) { 72 return (Constants.ACC_PRIVATE & access) != 0; 73 } 74 75 public static boolean isSynthetic(int access) { 76 return (Constants.ACC_SYNTHETIC & access) != 0; 77 } 78 79 // getPackage returns null on JDK 1.2 80 public static String getPackageName(Type type) { 81 return getPackageName(getClassName(type)); 82 } 83 84 public static String getPackageName(String className) { 85 int idx = className.lastIndexOf('.'); 86 return (idx < 0) ? "" : className.substring(0, idx); 87 } 88 89 public static String upperFirst(String s) { 90 if (s == null || s.length() == 0) { 91 return s; 92 } 93 return Character.toUpperCase(s.charAt(0)) + s.substring(1); 94 } 95 96 public static String getClassName(Type type) { 97 if (isPrimitive(type)) { 98 return (String)rtransforms.get(type.getDescriptor()); 99 } else if (isArray(type)) { 100 return getClassName(getComponentType(type)) + "[]"; 101 } else { 102 return type.getClassName(); 103 } 104 } 105 106 public static Type[] add(Type[] types, Type extra) { 107 if (types == null) { 108 return new Type[]{ extra }; 109 } else { 110 List list = Arrays.asList(types); 111 if (list.contains(extra)) { 112 return types; 113 } 114 Type[] copy = new Type[types.length + 1]; 115 System.arraycopy(types, 0, copy, 0, types.length); 116 copy[types.length] = extra; 117 return copy; 118 } 119 } 120 121 public static Type[] add(Type[] t1, Type[] t2) { 122 // TODO: set semantics? 123 Type[] all = new Type[t1.length + t2.length]; 124 System.arraycopy(t1, 0, all, 0, t1.length); 125 System.arraycopy(t2, 0, all, t1.length, t2.length); 126 return all; 127 } 128 129 public static Type fromInternalName(String name) { 130 // TODO; primitives? 131 return Type.getType("L" + name + ";"); 132 } 133 134 public static Type[] fromInternalNames(String[] names) { 135 if (names == null) { 136 return null; 137 } 138 Type[] types = new Type[names.length]; 139 for (int i = 0; i < names.length; i++) { 140 types[i] = fromInternalName(names[i]); 141 } 142 return types; 143 } 144 145 public static int getStackSize(Type[] types) { 146 int size = 0; 147 for (int i = 0; i < types.length; i++) { 148 size += types[i].getSize(); 149 } 150 return size; 151 } 152 153 public static String[] toInternalNames(Type[] types) { 154 if (types == null) { 155 return null; 156 } 157 String[] names = new String[types.length]; 158 for (int i = 0; i < types.length; i++) { 159 names[i] = types[i].getInternalName(); 160 } 161 return names; 162 } 163 164 public static Signature parseSignature(String s) { 165 int space = s.indexOf(' '); 166 int lparen = s.indexOf('(', space); 167 int rparen = s.indexOf(')', lparen); 168 String returnType = s.substring(0, space); 169 String methodName = s.substring(space + 1, lparen); 170 StringBuffer sb = new StringBuffer(); 171 sb.append('('); 172 for (Iterator it = parseTypes(s, lparen + 1, rparen).iterator(); it.hasNext();) { 173 sb.append(it.next()); 174 } 175 sb.append(')'); 176 sb.append(map(returnType)); 177 return new Signature(methodName, sb.toString()); 178 } 179 180 public static Type parseType(String s) { 181 return Type.getType(map(s)); 182 } 183 184 public static Type[] parseTypes(String s) { 185 List names = parseTypes(s, 0, s.length()); 186 Type[] types = new Type[names.size()]; 187 for (int i = 0; i < types.length; i++) { 188 types[i] = Type.getType((String)names.get(i)); 189 } 190 return types; 191 } 192 193 public static Signature parseConstructor(Type[] types) { 194 StringBuffer sb = new StringBuffer(); 195 sb.append("("); 196 for (int i = 0; i < types.length; i++) { 197 sb.append(types[i].getDescriptor()); 198 } 199 sb.append(")"); 200 sb.append("V"); 201 return new Signature(Constants.CONSTRUCTOR_NAME, sb.toString()); 202 } 203 204 public static Signature parseConstructor(String sig) { 205 return parseSignature("void <init>(" + sig + ")"); // TODO 206 } 207 208 private static List parseTypes(String s, int mark, int end) { 209 List types = new ArrayList(5); 210 for (;;) { 211 int next = s.indexOf(',', mark); 212 if (next < 0) { 213 break; 214 } 215 types.add(map(s.substring(mark, next).trim())); 216 mark = next + 1; 217 } 218 types.add(map(s.substring(mark, end).trim())); 219 return types; 220 } 221 222 private static String map(String type) { 223 if (type.equals("")) { 224 return type; 225 } 226 String t = (String)transforms.get(type); 227 if (t != null) { 228 return t; 229 } else if (type.indexOf('.') < 0) { 230 return map("java.lang." + type); 231 } else { 232 StringBuffer sb = new StringBuffer(); 233 int index = 0; 234 while ((index = type.indexOf("[]", index) + 1) > 0) { 235 sb.append('['); 236 } 237 type = type.substring(0, type.length() - sb.length() * 2); 238 sb.append('L').append(type.replace('.', '/')).append(';'); 239 return sb.toString(); 240 } 241 } 242 243 public static Type getBoxedType(Type type) { 244 switch (type.getSort()) { 245 case Type.CHAR: 246 return Constants.TYPE_CHARACTER; 247 case Type.BOOLEAN: 248 return Constants.TYPE_BOOLEAN; 249 case Type.DOUBLE: 250 return Constants.TYPE_DOUBLE; 251 case Type.FLOAT: 252 return Constants.TYPE_FLOAT; 253 case Type.LONG: 254 return Constants.TYPE_LONG; 255 case Type.INT: 256 return Constants.TYPE_INTEGER; 257 case Type.SHORT: 258 return Constants.TYPE_SHORT; 259 case Type.BYTE: 260 return Constants.TYPE_BYTE; 261 default: 262 return type; 263 } 264 } 265 266 public static Type getUnboxedType(Type type) { 267 if (Constants.TYPE_INTEGER.equals(type)) { 268 return Type.INT_TYPE; 269 } else if (Constants.TYPE_BOOLEAN.equals(type)) { 270 return Type.BOOLEAN_TYPE; 271 } else if (Constants.TYPE_DOUBLE.equals(type)) { 272 return Type.DOUBLE_TYPE; 273 } else if (Constants.TYPE_LONG.equals(type)) { 274 return Type.LONG_TYPE; 275 } else if (Constants.TYPE_CHARACTER.equals(type)) { 276 return Type.CHAR_TYPE; 277 } else if (Constants.TYPE_BYTE.equals(type)) { 278 return Type.BYTE_TYPE; 279 } else if (Constants.TYPE_FLOAT.equals(type)) { 280 return Type.FLOAT_TYPE; 281 } else if (Constants.TYPE_SHORT.equals(type)) { 282 return Type.SHORT_TYPE; 283 } else { 284 return type; 285 } 286 } 287 288 public static boolean isArray(Type type) { 289 return type.getSort() == Type.ARRAY; 290 } 291 292 public static Type getComponentType(Type type) { 293 if (!isArray(type)) { 294 throw new IllegalArgumentException("Type " + type + " is not an array"); 295 } 296 return Type.getType(type.getDescriptor().substring(1)); 297 } 298 299 public static boolean isPrimitive(Type type) { 300 switch (type.getSort()) { 301 case Type.ARRAY: 302 case Type.OBJECT: 303 return false; 304 default: 305 return true; 306 } 307 } 308 309 public static String emulateClassGetName(Type type) { 310 if (isArray(type)) { 311 return type.getDescriptor().replace('/', '.'); 312 } else { 313 return getClassName(type); 314 } 315 } 316 317 public static boolean isConstructor(MethodInfo method) { 318 return method.getSignature().getName().equals(Constants.CONSTRUCTOR_NAME); 319 } 320 321 public static Type[] getTypes(Class[] classes) { 322 if (classes == null) { 323 return null; 324 } 325 Type[] types = new Type[classes.length]; 326 for (int i = 0; i < classes.length; i++) { 327 types[i] = Type.getType(classes[i]); 328 } 329 return types; 330 } 331 332 public static int ICONST(int value) { 333 switch (value) { 334 case -1: return Constants.ICONST_M1; 335 case 0: return Constants.ICONST_0; 336 case 1: return Constants.ICONST_1; 337 case 2: return Constants.ICONST_2; 338 case 3: return Constants.ICONST_3; 339 case 4: return Constants.ICONST_4; 340 case 5: return Constants.ICONST_5; 341 } 342 return -1; // error 343 } 344 345 public static int LCONST(long value) { 346 if (value == 0L) { 347 return Constants.LCONST_0; 348 } else if (value == 1L) { 349 return Constants.LCONST_1; 350 } else { 351 return -1; // error 352 } 353 } 354 355 public static int FCONST(float value) { 356 if (value == 0f) { 357 return Constants.FCONST_0; 358 } else if (value == 1f) { 359 return Constants.FCONST_1; 360 } else if (value == 2f) { 361 return Constants.FCONST_2; 362 } else { 363 return -1; // error 364 } 365 } 366 367 public static int DCONST(double value) { 368 if (value == 0d) { 369 return Constants.DCONST_0; 370 } else if (value == 1d) { 371 return Constants.DCONST_1; 372 } else { 373 return -1; // error 374 } 375 } 376 377 public static int NEWARRAY(Type type) { 378 switch (type.getSort()) { 379 case Type.BYTE: 380 return Constants.T_BYTE; 381 case Type.CHAR: 382 return Constants.T_CHAR; 383 case Type.DOUBLE: 384 return Constants.T_DOUBLE; 385 case Type.FLOAT: 386 return Constants.T_FLOAT; 387 case Type.INT: 388 return Constants.T_INT; 389 case Type.LONG: 390 return Constants.T_LONG; 391 case Type.SHORT: 392 return Constants.T_SHORT; 393 case Type.BOOLEAN: 394 return Constants.T_BOOLEAN; 395 default: 396 return -1; // error 397 } 398 } 399 400 public static String escapeType(String s) { 401 StringBuffer sb = new StringBuffer(); 402 for (int i = 0, len = s.length(); i < len; i++) { 403 char c = s.charAt(i); 404 switch (c) { 405 case '$': sb.append("$24"); break; 406 case '.': sb.append("$2E"); break; 407 case '[': sb.append("$5B"); break; 408 case ';': sb.append("$3B"); break; 409 case '(': sb.append("$28"); break; 410 case ')': sb.append("$29"); break; 411 case '/': sb.append("$2F"); break; 412 default: 413 sb.append(c); 414 } 415 } 416 return sb.toString(); 417 } 418} 419