All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testifyproject.bytecode.Descriptor Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in org.testifyproject.testifyprojectpliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package org.testifyproject.testifyproject.bytecode;

import org.testifyproject.testifyproject.ClassPool;
import org.testifyproject.testifyproject.CtClass;
import org.testifyproject.testifyproject.CtPrimitiveType;
import org.testifyproject.testifyproject.NotFoundException;
import java.util.Map;

/**
 * A support class for org.testifyproject.testifyprojectaling with org.testifyproject.testifyprojectscriptors.
 *
 * 

See chapter 4.3 in "The Java Virtual Machine Specification (2nd ed.)" */ public class Descriptor { /** * Converts a class name into the internal representation used in * the JVM. * *

Note that toJvmName(toJvmName(s)) is equivalent * to toJvmName(s). */ public static String toJvmName(String classname) { return classname.replace('.', '/'); } /** * Converts a class name from the internal representation used in * the JVM to the normal one used in Java. * This method does not org.testifyproject.testifyprojectal with an array type name such as * "[Ljava/lang/Object;" and "[I;". For such names, use * toClassName(). * * @see #toClassName(String) */ public static String toJavaName(String classname) { return classname.replace('/', '.'); } /** * Returns the internal representation of the class name in the * JVM. */ public static String toJvmName(CtClass clazz) { if (clazz.isArray()) return of(clazz); else return toJvmName(clazz.getName()); } /** * Converts to a Java class name from a org.testifyproject.testifyprojectscriptor. * * @param org.testifyproject.testifyprojectscriptor type org.testifyproject.testifyprojectscriptor. */ public static String toClassName(String org.testifyproject.testifyprojectscriptor) { int arrayDim = 0; int i = 0; char c = org.testifyproject.testifyprojectscriptor.charAt(0); while (c == '[') { ++arrayDim; c = org.testifyproject.testifyprojectscriptor.charAt(++i); } String name; if (c == 'L') { int i2 = org.testifyproject.testifyprojectscriptor.indexOf(';', i++); name = org.testifyproject.testifyprojectscriptor.substring(i, i2).replace('/', '.'); i = i2; } else if (c == 'V') name = "void"; else if (c == 'I') name = "int"; else if (c == 'B') name = "byte"; else if (c == 'J') name = "long"; else if (c == 'D') name = "double"; else if (c == 'F') name = "float"; else if (c == 'C') name = "char"; else if (c == 'S') name = "short"; else if (c == 'Z') name = "boolean"; else throw new RuntimeException("bad org.testifyproject.testifyprojectscriptor: " + org.testifyproject.testifyprojectscriptor); if (i + 1 != org.testifyproject.testifyprojectscriptor.length()) throw new RuntimeException("multiple org.testifyproject.testifyprojectscriptors?: " + org.testifyproject.testifyprojectscriptor); if (arrayDim == 0) return name; else { StringBuffer sbuf = new StringBuffer(name); do { sbuf.append("[]"); } while (--arrayDim > 0); return sbuf.toString(); } } /** * Converts to a org.testifyproject.testifyprojectscriptor from a Java class name */ public static String of(String classname) { if (classname.equals("void")) return "V"; else if (classname.equals("int")) return "I"; else if (classname.equals("byte")) return "B"; else if (classname.equals("long")) return "J"; else if (classname.equals("double")) return "D"; else if (classname.equals("float")) return "F"; else if (classname.equals("char")) return "C"; else if (classname.equals("short")) return "S"; else if (classname.equals("boolean")) return "Z"; else return "L" + toJvmName(classname) + ";"; } /** * Substitutes a class name * in the given org.testifyproject.testifyprojectscriptor string. * * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor string * @param oldname replaced JVM class name * @param newname substituted JVM class name * * @see Descriptor#toJvmName(String) */ public static String rename(String org.testifyproject.testifyprojectsc, String oldname, String newname) { if (org.testifyproject.testifyprojectsc.indexOf(oldname) < 0) return org.testifyproject.testifyprojectsc; StringBuffer newdesc = new StringBuffer(); int head = 0; int i = 0; for (;;) { int j = org.testifyproject.testifyprojectsc.indexOf('L', i); if (j < 0) break; else if (org.testifyproject.testifyprojectsc.startsWith(oldname, j + 1) && org.testifyproject.testifyprojectsc.charAt(j + oldname.length() + 1) == ';') { newdesc.append(org.testifyproject.testifyprojectsc.substring(head, j)); newdesc.append('L'); newdesc.append(newname); newdesc.append(';'); head = i = j + oldname.length() + 2; } else { i = org.testifyproject.testifyprojectsc.indexOf(';', j) + 1; if (i < 1) break; // ';' was not found. } } if (head == 0) return org.testifyproject.testifyprojectsc; else { int len = org.testifyproject.testifyprojectsc.length(); if (head < len) newdesc.append(org.testifyproject.testifyprojectsc.substring(head, len)); return newdesc.toString(); } } /** * Substitutes class names in the given org.testifyproject.testifyprojectscriptor string * according to the given map. * * @param map a map between replaced and substituted * JVM class names. * @see Descriptor#toJvmName(String) */ public static String rename(String org.testifyproject.testifyprojectsc, Map map) { if (map == null) return org.testifyproject.testifyprojectsc; StringBuffer newdesc = new StringBuffer(); int head = 0; int i = 0; for (;;) { int j = org.testifyproject.testifyprojectsc.indexOf('L', i); if (j < 0) break; int k = org.testifyproject.testifyprojectsc.indexOf(';', j); if (k < 0) break; i = k + 1; String name = org.testifyproject.testifyprojectsc.substring(j + 1, k); String name2 = (String)map.get(name); if (name2 != null) { newdesc.append(org.testifyproject.testifyprojectsc.substring(head, j)); newdesc.append('L'); newdesc.append(name2); newdesc.append(';'); head = i; } } if (head == 0) return org.testifyproject.testifyprojectsc; else { int len = org.testifyproject.testifyprojectsc.length(); if (head < len) newdesc.append(org.testifyproject.testifyprojectsc.substring(head, len)); return newdesc.toString(); } } /** * Returns the org.testifyproject.testifyprojectscriptor representing the given type. */ public static String of(CtClass type) { StringBuffer sbuf = new StringBuffer(); toDescriptor(sbuf, type); return sbuf.toString(); } private static void toDescriptor(StringBuffer org.testifyproject.testifyprojectsc, CtClass type) { if (type.isArray()) { org.testifyproject.testifyprojectsc.append('['); try { toDescriptor(org.testifyproject.testifyprojectsc, type.getComponentType()); } catch (NotFoundException e) { org.testifyproject.testifyprojectsc.append('L'); String name = type.getName(); org.testifyproject.testifyprojectsc.append(toJvmName(name.substring(0, name.length() - 2))); org.testifyproject.testifyprojectsc.append(';'); } } else if (type.isPrimitive()) { CtPrimitiveType pt = (CtPrimitiveType)type; org.testifyproject.testifyprojectsc.append(pt.getDescriptor()); } else { // class type org.testifyproject.testifyprojectsc.append('L'); org.testifyproject.testifyprojectsc.append(type.getName().replace('.', '/')); org.testifyproject.testifyprojectsc.append(';'); } } /** * Returns the org.testifyproject.testifyprojectscriptor representing a constructor receiving * the given parameter types. * * @param paramTypes parameter types */ public static String ofConstructor(CtClass[] paramTypes) { return ofMethod(CtClass.voidType, paramTypes); } /** * Returns the org.testifyproject.testifyprojectscriptor representing a method that receives * the given parameter types and returns the given type. * * @param returnType return type * @param paramTypes parameter types */ public static String ofMethod(CtClass returnType, CtClass[] paramTypes) { StringBuffer org.testifyproject.testifyprojectsc = new StringBuffer(); org.testifyproject.testifyprojectsc.append('('); if (paramTypes != null) { int n = paramTypes.length; for (int i = 0; i < n; ++i) toDescriptor(org.testifyproject.testifyprojectsc, paramTypes[i]); } org.testifyproject.testifyprojectsc.append(')'); if (returnType != null) toDescriptor(org.testifyproject.testifyprojectsc, returnType); return org.testifyproject.testifyprojectsc.toString(); } /** * Returns the org.testifyproject.testifyprojectscriptor representing a list of parameter types. * For example, if the given parameter types are two int, * then this method returns "(II)". * * @param paramTypes parameter types */ public static String ofParameters(CtClass[] paramTypes) { return ofMethod(null, paramTypes); } /** * Appends a parameter type to the parameter list represented * by the given org.testifyproject.testifyprojectscriptor. * *

classname must not be an array type. * * @param classname parameter type (not primitive type) * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor */ public static String appendParameter(String classname, String org.testifyproject.testifyprojectsc) { int i = org.testifyproject.testifyprojectsc.indexOf(')'); if (i < 0) return org.testifyproject.testifyprojectsc; else { StringBuffer newdesc = new StringBuffer(); newdesc.append(org.testifyproject.testifyprojectsc.substring(0, i)); newdesc.append('L'); newdesc.append(classname.replace('.', '/')); newdesc.append(';'); newdesc.append(org.testifyproject.testifyprojectsc.substring(i)); return newdesc.toString(); } } /** * Inserts a parameter type at the beginning of the parameter * list represented * by the given org.testifyproject.testifyprojectscriptor. * *

classname must not be an array type. * * @param classname parameter type (not primitive type) * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor */ public static String insertParameter(String classname, String org.testifyproject.testifyprojectsc) { if (org.testifyproject.testifyprojectsc.charAt(0) != '(') return org.testifyproject.testifyprojectsc; else return "(L" + classname.replace('.', '/') + ';' + org.testifyproject.testifyprojectsc.substring(1); } /** * Appends a parameter type to the parameter list represented * by the given org.testifyproject.testifyprojectscriptor. The appended parameter becomes * the last parameter. * * @param type the type of the appended parameter. * @param org.testifyproject.testifyprojectscriptor the original org.testifyproject.testifyprojectscriptor. */ public static String appendParameter(CtClass type, String org.testifyproject.testifyprojectscriptor) { int i = org.testifyproject.testifyprojectscriptor.indexOf(')'); if (i < 0) return org.testifyproject.testifyprojectscriptor; else { StringBuffer newdesc = new StringBuffer(); newdesc.append(org.testifyproject.testifyprojectscriptor.substring(0, i)); toDescriptor(newdesc, type); newdesc.append(org.testifyproject.testifyprojectscriptor.substring(i)); return newdesc.toString(); } } /** * Inserts a parameter type at the beginning of the parameter * list represented * by the given org.testifyproject.testifyprojectscriptor. * * @param type the type of the inserted parameter. * @param org.testifyproject.testifyprojectscriptor the org.testifyproject.testifyprojectscriptor of the method. */ public static String insertParameter(CtClass type, String org.testifyproject.testifyprojectscriptor) { if (org.testifyproject.testifyprojectscriptor.charAt(0) != '(') return org.testifyproject.testifyprojectscriptor; else return "(" + of(type) + org.testifyproject.testifyprojectscriptor.substring(1); } /** * Changes the return type included in the given org.testifyproject.testifyprojectscriptor. * *

classname must not be an array type. * * @param classname return type * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor */ public static String changeReturnType(String classname, String org.testifyproject.testifyprojectsc) { int i = org.testifyproject.testifyprojectsc.indexOf(')'); if (i < 0) return org.testifyproject.testifyprojectsc; else { StringBuffer newdesc = new StringBuffer(); newdesc.append(org.testifyproject.testifyprojectsc.substring(0, i + 1)); newdesc.append('L'); newdesc.append(classname.replace('.', '/')); newdesc.append(';'); return newdesc.toString(); } } /** * Returns the CtClass objects representing the parameter * types specified by the given org.testifyproject.testifyprojectscriptor. * * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor * @param cp the class pool used for obtaining * a CtClass object. */ public static CtClass[] getParameterTypes(String org.testifyproject.testifyprojectsc, ClassPool cp) throws NotFoundException { if (org.testifyproject.testifyprojectsc.charAt(0) != '(') return null; else { int num = numOfParameters(org.testifyproject.testifyprojectsc); CtClass[] args = new CtClass[num]; int n = 0; int i = 1; do { i = toCtClass(cp, org.testifyproject.testifyprojectsc, i, args, n++); } while (i > 0); return args; } } /** * Returns true if the list of the parameter types of org.testifyproject.testifyprojectsc1 is equal to * that of org.testifyproject.testifyprojectsc2. * For example, "(II)V" and "(II)I" are equal. */ public static boolean eqParamTypes(String org.testifyproject.testifyprojectsc1, String org.testifyproject.testifyprojectsc2) { if (org.testifyproject.testifyprojectsc1.charAt(0) != '(') return false; for (int i = 0; true; ++i) { char c = org.testifyproject.testifyprojectsc1.charAt(i); if (c != org.testifyproject.testifyprojectsc2.charAt(i)) return false; if (c == ')') return true; } } /** * Returns the signature of the given org.testifyproject.testifyprojectscriptor. The signature does * not include the return type. For example, the signature of "(I)V" * is "(I)". */ public static String getParamDescriptor(String org.testifyproject.testifyprojectcl) { return org.testifyproject.testifyprojectcl.substring(0, org.testifyproject.testifyprojectcl.indexOf(')') + 1); } /** * Returns the CtClass object representing the return * type specified by the given org.testifyproject.testifyprojectscriptor. * * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor * @param cp the class pool used for obtaining * a CtClass object. */ public static CtClass getReturnType(String org.testifyproject.testifyprojectsc, ClassPool cp) throws NotFoundException { int i = org.testifyproject.testifyprojectsc.indexOf(')'); if (i < 0) return null; else { CtClass[] type = new CtClass[1]; toCtClass(cp, org.testifyproject.testifyprojectsc, i + 1, type, 0); return type[0]; } } /** * Returns the number of the prameters included in the given * org.testifyproject.testifyprojectscriptor. * * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor */ public static int numOfParameters(String org.testifyproject.testifyprojectsc) { int n = 0; int i = 1; for (;;) { char c = org.testifyproject.testifyprojectsc.charAt(i); if (c == ')') break; while (c == '[') c = org.testifyproject.testifyprojectsc.charAt(++i); if (c == 'L') { i = org.testifyproject.testifyprojectsc.indexOf(';', i) + 1; if (i <= 0) throw new IndexOutOfBoundsException("bad org.testifyproject.testifyprojectscriptor"); } else ++i; ++n; } return n; } /** * Returns a CtClass object representing the type * specified by the given org.testifyproject.testifyprojectscriptor. * *

This method works even if the package-class separator is * not / but . (period). For example, * it accepts Ljava.lang.Object; * as well as Ljava/lang/Object;. * * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor. * @param cp the class pool used for obtaining * a CtClass object. */ public static CtClass toCtClass(String org.testifyproject.testifyprojectsc, ClassPool cp) throws NotFoundException { CtClass[] clazz = new CtClass[1]; int res = toCtClass(cp, org.testifyproject.testifyprojectsc, 0, clazz, 0); if (res >= 0) return clazz[0]; else { // maybe, you forgot to surround the class name with // L and ;. It violates the protocol, but I'm tolerant... return cp.get(org.testifyproject.testifyprojectsc.replace('/', '.')); } } private static int toCtClass(ClassPool cp, String org.testifyproject.testifyprojectsc, int i, CtClass[] args, int n) throws NotFoundException { int i2; String name; int arrayDim = 0; char c = org.testifyproject.testifyprojectsc.charAt(i); while (c == '[') { ++arrayDim; c = org.testifyproject.testifyprojectsc.charAt(++i); } if (c == 'L') { i2 = org.testifyproject.testifyprojectsc.indexOf(';', ++i); name = org.testifyproject.testifyprojectsc.substring(i, i2++).replace('/', '.'); } else { CtClass type = toPrimitiveClass(c); if (type == null) return -1; // error i2 = i + 1; if (arrayDim == 0) { args[n] = type; return i2; // neither an array type or a class type } else name = type.getName(); } if (arrayDim > 0) { StringBuffer sbuf = new StringBuffer(name); while (arrayDim-- > 0) sbuf.append("[]"); name = sbuf.toString(); } args[n] = cp.get(name); return i2; } static CtClass toPrimitiveClass(char c) { CtClass type = null; switch (c) { case 'Z' : type = CtClass.booleanType; break; case 'C' : type = CtClass.charType; break; case 'B' : type = CtClass.byteType; break; case 'S' : type = CtClass.shortType; break; case 'I' : type = CtClass.intType; break; case 'J' : type = CtClass.longType; break; case 'F' : type = CtClass.floatType; break; case 'D' : type = CtClass.doubleType; break; case 'V' : type = CtClass.voidType; break; } return type; } /** * Computes the dimension of the array represented by the given * org.testifyproject.testifyprojectscriptor. For example, if the org.testifyproject.testifyprojectscriptor is "[[I", * then this method returns 2. * * @param org.testifyproject.testifyprojectsc the org.testifyproject.testifyprojectscriptor. * @return 0 if the org.testifyproject.testifyprojectscriptor does not represent an array type. */ public static int arrayDimension(String org.testifyproject.testifyprojectsc) { int dim = 0; while (org.testifyproject.testifyprojectsc.charAt(dim) == '[') ++dim; return dim; } /** * Returns the org.testifyproject.testifyprojectscriptor of the type of the array org.testifyproject.testifyprojectponent. * For example, if the given org.testifyproject.testifyprojectscriptor is * "[[Ljava/lang/String;" and the given dimension is 2, * then this method returns "Ljava/lang/String;". * * @param org.testifyproject.testifyprojectsc the org.testifyproject.testifyprojectscriptor. * @param dim the array dimension. */ public static String toArrayComponent(String org.testifyproject.testifyprojectsc, int dim) { return org.testifyproject.testifyprojectsc.substring(dim); } /** * Computes the data size specified by the given org.testifyproject.testifyprojectscriptor. * For example, if the org.testifyproject.testifyprojectscriptor is "D", this method returns 2. * *

If the org.testifyproject.testifyprojectscriptor represents a method type, this method returns * (the size of the returned value) - (the sum of the data sizes * of all the parameters). For example, if the org.testifyproject.testifyprojectscriptor is * "(I)D", then this method returns 1 (= 2 - 1). * * @param org.testifyproject.testifyprojectsc org.testifyproject.testifyprojectscriptor */ public static int dataSize(String org.testifyproject.testifyprojectsc) { return dataSize(org.testifyproject.testifyprojectsc, true); } /** * Computes the data size of parameters. * If one of the parameters is double type, the size of that parameter * is 2 words. For example, if the given org.testifyproject.testifyprojectscriptor is * "(IJ)D", then this method returns 3. The size of the * return type is not org.testifyproject.testifyprojectputed. * * @param org.testifyproject.testifyprojectsc a method org.testifyproject.testifyprojectscriptor. */ public static int paramSize(String org.testifyproject.testifyprojectsc) { return -dataSize(org.testifyproject.testifyprojectsc, false); } private static int dataSize(String org.testifyproject.testifyprojectsc, boolean withRet) { int n = 0; char c = org.testifyproject.testifyprojectsc.charAt(0); if (c == '(') { int i = 1; for (;;) { c = org.testifyproject.testifyprojectsc.charAt(i); if (c == ')') { c = org.testifyproject.testifyprojectsc.charAt(i + 1); break; } boolean array = false; while (c == '[') { array = true; c = org.testifyproject.testifyprojectsc.charAt(++i); } if (c == 'L') { i = org.testifyproject.testifyprojectsc.indexOf(';', i) + 1; if (i <= 0) throw new IndexOutOfBoundsException("bad org.testifyproject.testifyprojectscriptor"); } else ++i; if (!array && (c == 'J' || c == 'D')) n -= 2; else --n; } } if (withRet) if (c == 'J' || c == 'D') n += 2; else if (c != 'V') ++n; return n; } /** * Returns a human-readable representation of the * given org.testifyproject.testifyprojectscriptor. For example, Ljava/lang/Object; * is converted into java.lang.Object. * (I[I)V is converted into (int, int[]) * (the return type is ignored). */ public static String toString(String org.testifyproject.testifyprojectsc) { return PrettyPrinter.toString(org.testifyproject.testifyprojectsc); } static class PrettyPrinter { static String toString(String org.testifyproject.testifyprojectsc) { StringBuffer sbuf = new StringBuffer(); if (org.testifyproject.testifyprojectsc.charAt(0) == '(') { int pos = 1; sbuf.append('('); while (org.testifyproject.testifyprojectsc.charAt(pos) != ')') { if (pos > 1) sbuf.append(','); pos = readType(sbuf, pos, org.testifyproject.testifyprojectsc); } sbuf.append(')'); } else readType(sbuf, 0, org.testifyproject.testifyprojectsc); return sbuf.toString(); } static int readType(StringBuffer sbuf, int pos, String org.testifyproject.testifyprojectsc) { char c = org.testifyproject.testifyprojectsc.charAt(pos); int arrayDim = 0; while (c == '[') { arrayDim++; c = org.testifyproject.testifyprojectsc.charAt(++pos); } if (c == 'L') while (true) { c = org.testifyproject.testifyprojectsc.charAt(++pos); if (c == ';') break; if (c == '/') c = '.'; sbuf.append(c); } else { CtClass t = toPrimitiveClass(c); sbuf.append(t.getName()); } while (arrayDim-- > 0) sbuf.append("[]"); return pos + 1; } } /** * An Iterator over a org.testifyproject.testifyprojectscriptor. */ public static class Iterator { private String org.testifyproject.testifyprojectsc; private int index, curPos; private boolean param; /** * Constructs an iterator. * * @param s org.testifyproject.testifyprojectscriptor. */ public Iterator(String s) { org.testifyproject.testifyprojectsc = s; index = curPos = 0; param = false; } /** * Returns true if the iteration has more elements. */ public boolean hasNext() { return index < org.testifyproject.testifyprojectsc.length(); } /** * Returns true if the current element is a parameter type. */ public boolean isParameter() { return param; } /** * Returns the first character of the current element. */ public char currentChar() { return org.testifyproject.testifyprojectsc.charAt(curPos); } /** * Returns true if the current element is double or long type. */ public boolean is2byte() { char c = currentChar(); return c == 'D' || c == 'J'; } /** * Returns the position of the next type character. * That type character becomes a new current element. */ public int next() { int nextPos = index; char c = org.testifyproject.testifyprojectsc.charAt(nextPos); if (c == '(') { ++index; c = org.testifyproject.testifyprojectsc.charAt(++nextPos); param = true; } if (c == ')') { ++index; c = org.testifyproject.testifyprojectsc.charAt(++nextPos); param = false; } while (c == '[') c = org.testifyproject.testifyprojectsc.charAt(++nextPos); if (c == 'L') { nextPos = org.testifyproject.testifyprojectsc.indexOf(';', nextPos) + 1; if (nextPos <= 0) throw new IndexOutOfBoundsException("bad org.testifyproject.testifyprojectscriptor"); } else ++nextPos; curPos = index; index = nextPos; return curPos; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy