jaroslav@1646: /* jaroslav@1646: * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. jaroslav@1646: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1646: * jaroslav@1646: * This code is free software; you can redistribute it and/or modify it jaroslav@1646: * under the terms of the GNU General Public License version 2 only, as jaroslav@1646: * published by the Free Software Foundation. Oracle designates this jaroslav@1646: * particular file as subject to the "Classpath" exception as provided jaroslav@1646: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1646: * jaroslav@1646: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1646: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1646: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1646: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1646: * accompanied this code). jaroslav@1646: * jaroslav@1646: * You should have received a copy of the GNU General Public License version jaroslav@1646: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1646: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1646: * jaroslav@1646: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1646: * or visit www.oracle.com if you need additional information or have any jaroslav@1646: * questions. jaroslav@1646: */ jaroslav@1646: jaroslav@1646: package sun.invoke.util; jaroslav@1646: jaroslav@1646: import java.lang.invoke.MethodType; jaroslav@1646: import java.util.ArrayList; jaroslav@1646: import java.util.List; jaroslav@1646: jaroslav@1646: /** jaroslav@1646: * Utility routines for dealing with bytecode-level signatures. jaroslav@1646: * @author jrose jaroslav@1646: */ jaroslav@1646: public class BytecodeDescriptor { jaroslav@1646: jaroslav@1646: private BytecodeDescriptor() { } // cannot instantiate jaroslav@1646: jaroslav@1646: public static List> parseMethod(String bytecodeSignature, ClassLoader loader) { jaroslav@1646: return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader); jaroslav@1646: } jaroslav@1646: jaroslav@1646: static List> parseMethod(String bytecodeSignature, jaroslav@1646: int start, int end, ClassLoader loader) { jaroslav@1646: if (loader == null) jaroslav@1646: loader = ClassLoader.getSystemClassLoader(); jaroslav@1646: String str = bytecodeSignature; jaroslav@1646: int[] i = {start}; jaroslav@1646: ArrayList> ptypes = new ArrayList>(); jaroslav@1646: if (i[0] < end && str.charAt(i[0]) == '(') { jaroslav@1646: ++i[0]; // skip '(' jaroslav@1646: while (i[0] < end && str.charAt(i[0]) != ')') { jaroslav@1646: Class pt = parseSig(str, i, end, loader); jaroslav@1646: if (pt == null || pt == void.class) jaroslav@1646: parseError(str, "bad argument type"); jaroslav@1646: ptypes.add(pt); jaroslav@1646: } jaroslav@1646: ++i[0]; // skip ')' jaroslav@1646: } else { jaroslav@1646: parseError(str, "not a method type"); jaroslav@1646: } jaroslav@1646: Class rtype = parseSig(str, i, end, loader); jaroslav@1646: if (rtype == null || i[0] != end) jaroslav@1646: parseError(str, "bad return type"); jaroslav@1646: ptypes.add(rtype); jaroslav@1646: return ptypes; jaroslav@1646: } jaroslav@1646: jaroslav@1646: static private void parseError(String str, String msg) { jaroslav@1646: throw new IllegalArgumentException("bad signature: "+str+": "+msg); jaroslav@1646: } jaroslav@1646: jaroslav@1646: static private Class parseSig(String str, int[] i, int end, ClassLoader loader) { jaroslav@1646: if (i[0] == end) return null; jaroslav@1646: char c = str.charAt(i[0]++); jaroslav@1646: if (c == 'L') { jaroslav@1646: int begc = i[0], endc = str.indexOf(';', begc); jaroslav@1646: if (endc < 0) return null; jaroslav@1646: i[0] = endc+1; jaroslav@1646: String name = str.substring(begc, endc).replace('/', '.'); jaroslav@1646: try { jaroslav@1646: return loader.loadClass(name); jaroslav@1646: } catch (ClassNotFoundException ex) { jaroslav@1646: throw new TypeNotPresentException(name, ex); jaroslav@1646: } jaroslav@1646: } else if (c == '[') { jaroslav@1646: Class t = parseSig(str, i, end, loader); jaroslav@1646: if (t != null) jaroslav@1646: t = java.lang.reflect.Array.newInstance(t, 0).getClass(); jaroslav@1646: return t; jaroslav@1646: } else { jaroslav@1646: return Wrapper.forBasicType(c).primitiveType(); jaroslav@1646: } jaroslav@1646: } jaroslav@1646: jaroslav@1646: public static String unparse(Class type) { jaroslav@1646: StringBuilder sb = new StringBuilder(); jaroslav@1646: unparseSig(type, sb); jaroslav@1646: return sb.toString(); jaroslav@1646: } jaroslav@1646: jaroslav@1646: public static String unparse(MethodType type) { jaroslav@1646: return unparseMethod(type.returnType(), type.parameterList()); jaroslav@1646: } jaroslav@1646: jaroslav@1646: public static String unparse(Object type) { jaroslav@1646: if (type instanceof Class) jaroslav@1646: return unparse((Class) type); jaroslav@1646: if (type instanceof MethodType) jaroslav@1646: return unparse((MethodType) type); jaroslav@1646: return (String) type; jaroslav@1646: } jaroslav@1646: jaroslav@1646: public static String unparseMethod(Class rtype, List> ptypes) { jaroslav@1646: StringBuilder sb = new StringBuilder(); jaroslav@1646: sb.append('('); jaroslav@1646: for (Class pt : ptypes) jaroslav@1646: unparseSig(pt, sb); jaroslav@1646: sb.append(')'); jaroslav@1646: unparseSig(rtype, sb); jaroslav@1646: return sb.toString(); jaroslav@1646: } jaroslav@1646: jaroslav@1646: static private void unparseSig(Class t, StringBuilder sb) { jaroslav@1646: char c = Wrapper.forBasicType(t).basicTypeChar(); jaroslav@1646: if (c != 'L') { jaroslav@1646: sb.append(c); jaroslav@1646: } else { jaroslav@1646: boolean lsemi = (!t.isArray()); jaroslav@1646: if (lsemi) sb.append('L'); jaroslav@1646: sb.append(t.getName().replace('.', '/')); jaroslav@1646: if (lsemi) sb.append(';'); jaroslav@1646: } jaroslav@1646: } jaroslav@1646: jaroslav@1646: }