jjg@46: /* jjg@46: * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. jjg@46: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@46: * jjg@46: * This code is free software; you can redistribute it and/or modify it jjg@46: * under the terms of the GNU General Public License version 2 only, as jjg@46: * published by the Free Software Foundation. Sun designates this jjg@46: * particular file as subject to the "Classpath" exception as provided jjg@46: * by Sun in the LICENSE file that accompanied this code. jjg@46: * jjg@46: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@46: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@46: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@46: * version 2 for more details (a copy is included in the LICENSE file that jjg@46: * accompanied this code). jjg@46: * jjg@46: * You should have received a copy of the GNU General Public License version jjg@46: * 2 along with this work; if not, write to the Free Software Foundation, jjg@46: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@46: * jjg@46: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, jjg@46: * CA 95054 USA or visit www.sun.com if you need additional information or jjg@46: * have any questions. jjg@46: */ jjg@46: jjg@46: package com.sun.tools.classfile; jjg@46: jjg@46: import java.util.ArrayList; jjg@46: import java.util.List; jjg@46: jjg@46: /** jjg@46: * See JVMS3 4.4.4. jjg@46: * jjg@46: *

This is NOT part of any API supported by Sun Microsystems. If jjg@46: * you write code that depends on this, you do so at your own risk. jjg@46: * This code and its internal interfaces are subject to change or jjg@46: * deletion without notice. jjg@46: */ jjg@46: public class Signature extends Descriptor { jjg@46: jjg@46: public Signature(int index) { jjg@46: super(index); jjg@46: } jjg@46: jjg@46: public Type getType(ConstantPool constant_pool) throws ConstantPoolException { jjg@46: if (type == null) jjg@46: type = parse(getValue(constant_pool)); jjg@46: return type; jjg@46: } jjg@46: jjg@46: @Override jjg@46: public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException { jjg@46: Type.MethodType m = (Type.MethodType) getType(constant_pool); jjg@46: return m.argTypes.size(); jjg@46: } jjg@46: jjg@46: @Override jjg@46: public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException { jjg@46: Type.MethodType m = (Type.MethodType) getType(constant_pool); jjg@46: StringBuilder sb = new StringBuilder(); jjg@46: sb.append("("); jjg@46: String sep = ""; jjg@46: for (Type argType: m.argTypes) { jjg@46: sb.append(sep); jjg@46: sb.append(argType); jjg@46: sep = ", "; jjg@46: } jjg@46: sb.append(")"); jjg@46: return sb.toString(); jjg@46: } jjg@46: jjg@46: @Override jjg@46: public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException { jjg@46: Type.MethodType m = (Type.MethodType) getType(constant_pool); jjg@46: return m.returnType.toString(); jjg@46: } jjg@46: jjg@46: @Override jjg@46: public String getFieldType(ConstantPool constant_pool) throws ConstantPoolException { jjg@46: return getType(constant_pool).toString(); jjg@46: } jjg@46: jjg@46: private Type parse(String sig) { jjg@46: this.sig = sig; jjg@46: sigp = 0; jjg@46: jjg@46: List typeArgTypes = null; jjg@46: if (sig.charAt(sigp) == '<') jjg@46: typeArgTypes = parseTypeArgTypes(); jjg@46: jjg@46: if (sig.charAt(sigp) == '(') { jjg@46: List argTypes = parseTypeSignatures(')'); jjg@46: Type returnType = parseTypeSignature(); jjg@46: List throwsTypes = null; jjg@46: while (sigp < sig.length() && sig.charAt(sigp) == '^') { jjg@46: sigp++; jjg@46: if (throwsTypes == null) jjg@46: throwsTypes = new ArrayList(); jjg@46: throwsTypes.add(parseTypeSignature()); jjg@46: } jjg@46: return new Type.MethodType(typeArgTypes, argTypes, returnType, throwsTypes); jjg@46: } else { jjg@46: Type t = parseTypeSignature(); jjg@46: if (typeArgTypes == null && sigp == sig.length()) jjg@46: return t; jjg@46: Type superclass = t; jjg@46: List superinterfaces = new ArrayList(); jjg@46: while (sigp < sig.length()) jjg@46: superinterfaces.add(parseTypeSignature()); jjg@46: return new Type.ClassSigType(typeArgTypes, superclass, superinterfaces); jjg@46: jjg@46: } jjg@46: } jjg@46: jjg@46: private Type parseTypeSignature() { jjg@46: switch (sig.charAt(sigp)) { jjg@46: case 'B': jjg@46: sigp++; jjg@46: return new Type.SimpleType("byte"); jjg@46: jjg@46: case 'C': jjg@46: sigp++; jjg@46: return new Type.SimpleType("char"); jjg@46: jjg@46: case 'D': jjg@46: sigp++; jjg@46: return new Type.SimpleType("double"); jjg@46: jjg@46: case 'F': jjg@46: sigp++; jjg@46: return new Type.SimpleType("float"); jjg@46: jjg@46: case 'I': jjg@46: sigp++; jjg@46: return new Type.SimpleType("int"); jjg@46: jjg@46: case 'J': jjg@46: sigp++; jjg@46: return new Type.SimpleType("long"); jjg@46: jjg@46: case 'L': jjg@46: return parseClassTypeSignature(); jjg@46: jjg@46: case 'S': jjg@46: sigp++; jjg@46: return new Type.SimpleType("short"); jjg@46: jjg@46: case 'T': jjg@46: return parseTypeVariableSignature(); jjg@46: jjg@46: case 'V': jjg@46: sigp++; jjg@46: return new Type.SimpleType("void"); jjg@46: jjg@46: case 'Z': jjg@46: sigp++; jjg@46: return new Type.SimpleType("boolean"); jjg@46: jjg@46: case '[': jjg@46: sigp++; jjg@46: return new Type.ArrayType(parseTypeSignature()); jjg@46: jjg@46: case '*': jjg@46: sigp++; jjg@46: return new Type.WildcardType(); jjg@46: jjg@46: case '+': jjg@46: sigp++; jjg@46: return new Type.WildcardType("extends", parseTypeSignature()); jjg@46: jjg@46: case '-': jjg@46: sigp++; jjg@46: return new Type.WildcardType("super", parseTypeSignature()); jjg@46: jjg@46: default: jjg@46: throw new IllegalStateException(debugInfo()); jjg@46: } jjg@46: } jjg@46: jjg@46: private List parseTypeSignatures(char term) { jjg@46: sigp++; jjg@46: List types = new ArrayList(); jjg@46: while (sig.charAt(sigp) != term) jjg@46: types.add(parseTypeSignature()); jjg@46: sigp++; jjg@46: return types; jjg@46: } jjg@46: jjg@46: private Type parseClassTypeSignature() { jjg@46: assert sig.charAt(sigp) == 'L'; jjg@46: sigp++; jjg@46: return parseClassTypeSignatureRest(); jjg@46: } jjg@46: jjg@46: private Type parseClassTypeSignatureRest() { jjg@46: StringBuilder sb = new StringBuilder(); jjg@46: Type t = null; jjg@46: char sigch; jjg@46: while (true) { jjg@46: switch (sigch = sig.charAt(sigp)) { jjg@46: case '/': jjg@46: sigp++; jjg@46: sb.append("."); jjg@46: break; jjg@46: jjg@46: case '.': jjg@46: sigp++; jjg@46: if (t == null) jjg@46: t = new Type.SimpleType(sb.toString()); jjg@46: return new Type.InnerClassType(t, parseClassTypeSignatureRest()); jjg@46: jjg@46: case ';': jjg@46: sigp++; jjg@46: if (t == null) jjg@46: t = new Type.SimpleType(sb.toString()); jjg@46: return t; jjg@46: jjg@46: case '<': jjg@46: List argTypes = parseTypeSignatures('>'); jjg@46: t = new Type.ClassType(sb.toString(), argTypes); jjg@46: break; jjg@46: jjg@46: default: jjg@46: sigp++; jjg@46: sb.append(sigch); jjg@46: break; jjg@46: } jjg@46: } jjg@46: } jjg@46: jjg@46: private List parseTypeArgTypes() { jjg@46: assert sig.charAt(sigp) == '<'; jjg@46: sigp++; jjg@46: List types = null; jjg@46: types = new ArrayList(); jjg@46: while (sig.charAt(sigp) != '>') jjg@46: types.add(parseTypeArgType()); jjg@46: sigp++; jjg@46: return types; jjg@46: } jjg@46: jjg@46: private Type parseTypeArgType() { jjg@46: int sep = sig.indexOf(":", sigp); jjg@46: String name = sig.substring(sigp, sep); jjg@46: Type classBound = null; jjg@46: List interfaceBounds = null; jjg@46: sigp = sep + 1; jjg@46: if (sig.charAt(sigp) != ':') jjg@46: classBound = parseTypeSignature(); jjg@46: while (sig.charAt(sigp) == ':') { jjg@46: sigp++; jjg@46: if (interfaceBounds == null) jjg@46: interfaceBounds = new ArrayList(); jjg@46: interfaceBounds.add(parseTypeSignature()); jjg@46: } jjg@46: return new Type.TypeArgType(name, classBound, interfaceBounds); jjg@46: } jjg@46: jjg@46: private Type parseTypeVariableSignature() { jjg@46: sigp++; jjg@46: int sep = sig.indexOf(';', sigp); jjg@46: Type t = new Type.SimpleType(sig.substring(sigp, sep)); jjg@46: sigp = sep + 1; jjg@46: return t; jjg@46: } jjg@46: jjg@46: private String debugInfo() { jjg@46: return sig.substring(0, sigp) + "!" + sig.charAt(sigp) + "!" + sig.substring(sigp+1); jjg@46: } jjg@46: jjg@46: private String sig; jjg@46: private int sigp; jjg@46: jjg@46: private Type type; jjg@46: }