jjg@46: /*
xdono@54: * Copyright 2007-2008 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: }