001 /*
002 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.classfile;
027
028 import java.util.ArrayList;
029 import java.util.List;
030
031 /**
032 * See JVMS3 4.4.4.
033 *
034 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
035 * you write code that depends on this, you do so at your own risk.
036 * This code and its internal interfaces are subject to change or
037 * deletion without notice.</b>
038 */
039 public class Signature extends Descriptor {
040
041 public Signature(int index) {
042 super(index);
043 }
044
045 public Type getType(ConstantPool constant_pool) throws ConstantPoolException {
046 if (type == null)
047 type = parse(getValue(constant_pool));
048 return type;
049 }
050
051 @Override
052 public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException {
053 Type.MethodType m = (Type.MethodType) getType(constant_pool);
054 return m.argTypes.size();
055 }
056
057 @Override
058 public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException {
059 Type.MethodType m = (Type.MethodType) getType(constant_pool);
060 StringBuilder sb = new StringBuilder();
061 sb.append("(");
062 String sep = "";
063 for (Type argType: m.argTypes) {
064 sb.append(sep);
065 sb.append(argType);
066 sep = ", ";
067 }
068 sb.append(")");
069 return sb.toString();
070 }
071
072 @Override
073 public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException {
074 Type.MethodType m = (Type.MethodType) getType(constant_pool);
075 return m.returnType.toString();
076 }
077
078 @Override
079 public String getFieldType(ConstantPool constant_pool) throws ConstantPoolException {
080 return getType(constant_pool).toString();
081 }
082
083 private Type parse(String sig) {
084 this.sig = sig;
085 sigp = 0;
086
087 List<Type> typeArgTypes = null;
088 if (sig.charAt(sigp) == '<')
089 typeArgTypes = parseTypeArgTypes();
090
091 if (sig.charAt(sigp) == '(') {
092 List<Type> argTypes = parseTypeSignatures(')');
093 Type returnType = parseTypeSignature();
094 List<Type> throwsTypes = null;
095 while (sigp < sig.length() && sig.charAt(sigp) == '^') {
096 sigp++;
097 if (throwsTypes == null)
098 throwsTypes = new ArrayList<Type>();
099 throwsTypes.add(parseTypeSignature());
100 }
101 return new Type.MethodType(typeArgTypes, argTypes, returnType, throwsTypes);
102 } else {
103 Type t = parseTypeSignature();
104 if (typeArgTypes == null && sigp == sig.length())
105 return t;
106 Type superclass = t;
107 List<Type> superinterfaces = new ArrayList<Type>();
108 while (sigp < sig.length())
109 superinterfaces.add(parseTypeSignature());
110 return new Type.ClassSigType(typeArgTypes, superclass, superinterfaces);
111
112 }
113 }
114
115 private Type parseTypeSignature() {
116 switch (sig.charAt(sigp)) {
117 case 'B':
118 sigp++;
119 return new Type.SimpleType("byte");
120
121 case 'C':
122 sigp++;
123 return new Type.SimpleType("char");
124
125 case 'D':
126 sigp++;
127 return new Type.SimpleType("double");
128
129 case 'F':
130 sigp++;
131 return new Type.SimpleType("float");
132
133 case 'I':
134 sigp++;
135 return new Type.SimpleType("int");
136
137 case 'J':
138 sigp++;
139 return new Type.SimpleType("long");
140
141 case 'L':
142 return parseClassTypeSignature();
143
144 case 'S':
145 sigp++;
146 return new Type.SimpleType("short");
147
148 case 'T':
149 return parseTypeVariableSignature();
150
151 case 'V':
152 sigp++;
153 return new Type.SimpleType("void");
154
155 case 'Z':
156 sigp++;
157 return new Type.SimpleType("boolean");
158
159 case '[':
160 sigp++;
161 return new Type.ArrayType(parseTypeSignature());
162
163 case '*':
164 sigp++;
165 return new Type.WildcardType();
166
167 case '+':
168 sigp++;
169 return new Type.WildcardType("extends", parseTypeSignature());
170
171 case '-':
172 sigp++;
173 return new Type.WildcardType("super", parseTypeSignature());
174
175 default:
176 throw new IllegalStateException(debugInfo());
177 }
178 }
179
180 private List<Type> parseTypeSignatures(char term) {
181 sigp++;
182 List<Type> types = new ArrayList<Type>();
183 while (sig.charAt(sigp) != term)
184 types.add(parseTypeSignature());
185 sigp++;
186 return types;
187 }
188
189 private Type parseClassTypeSignature() {
190 assert sig.charAt(sigp) == 'L';
191 sigp++;
192 return parseClassTypeSignatureRest();
193 }
194
195 private Type parseClassTypeSignatureRest() {
196 StringBuilder sb = new StringBuilder();
197 Type t = null;
198 char sigch;
199 while (true) {
200 switch (sigch = sig.charAt(sigp)) {
201 case '/':
202 sigp++;
203 sb.append(".");
204 break;
205
206 case '.':
207 sigp++;
208 if (t == null)
209 t = new Type.SimpleType(sb.toString());
210 return new Type.InnerClassType(t, parseClassTypeSignatureRest());
211
212 case ';':
213 sigp++;
214 if (t == null)
215 t = new Type.SimpleType(sb.toString());
216 return t;
217
218 case '<':
219 List<Type> argTypes = parseTypeSignatures('>');
220 t = new Type.ClassType(sb.toString(), argTypes);
221 break;
222
223 default:
224 sigp++;
225 sb.append(sigch);
226 break;
227 }
228 }
229 }
230
231 private List<Type> parseTypeArgTypes() {
232 assert sig.charAt(sigp) == '<';
233 sigp++;
234 List<Type> types = null;
235 types = new ArrayList<Type>();
236 while (sig.charAt(sigp) != '>')
237 types.add(parseTypeArgType());
238 sigp++;
239 return types;
240 }
241
242 private Type parseTypeArgType() {
243 int sep = sig.indexOf(":", sigp);
244 String name = sig.substring(sigp, sep);
245 Type classBound = null;
246 List<Type> interfaceBounds = null;
247 sigp = sep + 1;
248 if (sig.charAt(sigp) != ':')
249 classBound = parseTypeSignature();
250 while (sig.charAt(sigp) == ':') {
251 sigp++;
252 if (interfaceBounds == null)
253 interfaceBounds = new ArrayList<Type>();
254 interfaceBounds.add(parseTypeSignature());
255 }
256 return new Type.TypeArgType(name, classBound, interfaceBounds);
257 }
258
259 private Type parseTypeVariableSignature() {
260 sigp++;
261 int sep = sig.indexOf(';', sigp);
262 Type t = new Type.SimpleType(sig.substring(sigp, sep));
263 sigp = sep + 1;
264 return t;
265 }
266
267 private String debugInfo() {
268 return sig.substring(0, sigp) + "!" + sig.charAt(sigp) + "!" + sig.substring(sigp+1);
269 }
270
271 private String sig;
272 private int sigp;
273
274 private Type type;
275 }