jjg@46: /* ohair@554: * Copyright (c) 2007, 2008, Oracle and/or its affiliates. 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 ohair@554: * published by the Free Software Foundation. Oracle designates this jjg@46: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle 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: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * 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@427: import com.sun.tools.classfile.Type.*; jjg@46: jjg@46: /** jjg@46: * See JVMS3 4.4.4. jjg@46: * jjg@581: *

This is NOT part of any supported API. jjg@581: * If 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@427: MethodType m = (MethodType) getType(constant_pool); jjg@427: return m.paramTypes.size(); jjg@46: } jjg@46: jjg@46: @Override jjg@46: public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException { jjg@427: MethodType m = (MethodType) getType(constant_pool); jjg@46: StringBuilder sb = new StringBuilder(); jjg@46: sb.append("("); jjg@46: String sep = ""; jjg@427: for (Type paramType: m.paramTypes) { jjg@46: sb.append(sep); jjg@427: sb.append(paramType); 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@427: MethodType m = (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@427: List typeParamTypes = null; jjg@46: if (sig.charAt(sigp) == '<') jjg@427: typeParamTypes = parseTypeParamTypes(); jjg@46: jjg@46: if (sig.charAt(sigp) == '(') { jjg@427: List paramTypes = 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@427: return new MethodType(typeParamTypes, paramTypes, returnType, throwsTypes); jjg@46: } else { jjg@46: Type t = parseTypeSignature(); jjg@427: if (typeParamTypes == null && sigp == sig.length()) jjg@46: return t; jjg@46: Type superclass = t; jjg@427: List superinterfaces = null; jjg@427: while (sigp < sig.length()) { jjg@427: if (superinterfaces == null) jjg@427: superinterfaces = new ArrayList(); jjg@46: superinterfaces.add(parseTypeSignature()); jjg@427: } jjg@427: return new ClassSigType(typeParamTypes, 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@427: return new SimpleType("byte"); jjg@46: jjg@46: case 'C': jjg@46: sigp++; jjg@427: return new SimpleType("char"); jjg@46: jjg@46: case 'D': jjg@46: sigp++; jjg@427: return new SimpleType("double"); jjg@46: jjg@46: case 'F': jjg@46: sigp++; jjg@427: return new SimpleType("float"); jjg@46: jjg@46: case 'I': jjg@46: sigp++; jjg@427: return new SimpleType("int"); jjg@46: jjg@46: case 'J': jjg@46: sigp++; jjg@427: return new SimpleType("long"); jjg@46: jjg@46: case 'L': jjg@46: return parseClassTypeSignature(); jjg@46: jjg@46: case 'S': jjg@46: sigp++; jjg@427: return new SimpleType("short"); jjg@46: jjg@46: case 'T': jjg@46: return parseTypeVariableSignature(); jjg@46: jjg@46: case 'V': jjg@46: sigp++; jjg@427: return new SimpleType("void"); jjg@46: jjg@46: case 'Z': jjg@46: sigp++; jjg@427: return new SimpleType("boolean"); jjg@46: jjg@46: case '[': jjg@46: sigp++; jjg@427: return new ArrayType(parseTypeSignature()); jjg@46: jjg@46: case '*': jjg@46: sigp++; jjg@427: return new WildcardType(); jjg@46: jjg@46: case '+': jjg@46: sigp++; jjg@427: return new WildcardType(WildcardType.Kind.EXTENDS, parseTypeSignature()); jjg@46: jjg@46: case '-': jjg@46: sigp++; jjg@427: return new WildcardType(WildcardType.Kind.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@427: List argTypes = null; jjg@427: ClassType t = null; jjg@427: char sigch ; jjg@427: jjg@427: do { jjg@46: switch (sigch = sig.charAt(sigp)) { jjg@427: case '<': jjg@427: argTypes = parseTypeSignatures('>'); jjg@46: break; jjg@46: jjg@46: case '.': jjg@46: case ';': jjg@46: sigp++; jjg@427: t = new ClassType(t, sb.toString(), argTypes); jjg@427: sb.setLength(0); jjg@427: argTypes = null; jjg@46: break; jjg@46: jjg@46: default: jjg@46: sigp++; jjg@46: sb.append(sigch); jjg@46: break; jjg@46: } jjg@427: } while (sigch != ';'); jjg@427: jjg@427: return t; jjg@46: } jjg@46: jjg@427: private List parseTypeParamTypes() { jjg@46: assert sig.charAt(sigp) == '<'; jjg@46: sigp++; jjg@427: List types = new ArrayList(); jjg@46: while (sig.charAt(sigp) != '>') jjg@427: types.add(parseTypeParamType()); jjg@46: sigp++; jjg@46: return types; jjg@46: } jjg@46: jjg@427: private TypeParamType parseTypeParamType() { 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@427: return new TypeParamType(name, classBound, interfaceBounds); jjg@46: } jjg@46: jjg@46: private Type parseTypeVariableSignature() { jjg@46: sigp++; jjg@46: int sep = sig.indexOf(';', sigp); jjg@427: Type t = new 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: }