1 /* 2 * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.classfile; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 import com.sun.tools.classfile.Type.*; 31 32 /** 33 * See JVMS 4.4.4. 34 * 35 * <p><b>This is NOT part of any supported API. 36 * If you write code that depends on this, you do so at your own risk. 37 * This code and its internal interfaces are subject to change or 38 * deletion without notice.</b> 39 */ 40 public class Signature extends Descriptor { 41 Signature(int index)42 public Signature(int index) { 43 super(index); 44 } 45 getType(ConstantPool constant_pool)46 public Type getType(ConstantPool constant_pool) throws ConstantPoolException { 47 if (type == null) 48 type = parse(getValue(constant_pool)); 49 return type; 50 } 51 52 @Override getParameterCount(ConstantPool constant_pool)53 public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException { 54 MethodType m = (MethodType) getType(constant_pool); 55 return m.paramTypes.size(); 56 } 57 58 @Override getParameterTypes(ConstantPool constant_pool)59 public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException { 60 MethodType m = (MethodType) getType(constant_pool); 61 StringBuilder sb = new StringBuilder(); 62 sb.append("("); 63 String sep = ""; 64 for (Type paramType: m.paramTypes) { 65 sb.append(sep); 66 sb.append(paramType); 67 sep = ", "; 68 } 69 sb.append(")"); 70 return sb.toString(); 71 } 72 73 @Override getReturnType(ConstantPool constant_pool)74 public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException { 75 MethodType m = (MethodType) getType(constant_pool); 76 return m.returnType.toString(); 77 } 78 79 @Override getFieldType(ConstantPool constant_pool)80 public String getFieldType(ConstantPool constant_pool) throws ConstantPoolException { 81 return getType(constant_pool).toString(); 82 } 83 parse(String sig)84 private Type parse(String sig) { 85 this.sig = sig; 86 sigp = 0; 87 88 List<TypeParamType> typeParamTypes = null; 89 if (sig.charAt(sigp) == '<') 90 typeParamTypes = parseTypeParamTypes(); 91 92 if (sig.charAt(sigp) == '(') { 93 List<Type> paramTypes = parseTypeSignatures(')'); 94 Type returnType = parseTypeSignature(); 95 List<Type> throwsTypes = null; 96 while (sigp < sig.length() && sig.charAt(sigp) == '^') { 97 sigp++; 98 if (throwsTypes == null) 99 throwsTypes = new ArrayList<Type>(); 100 throwsTypes.add(parseTypeSignature()); 101 } 102 return new MethodType(typeParamTypes, paramTypes, returnType, throwsTypes); 103 } else { 104 Type t = parseTypeSignature(); 105 if (typeParamTypes == null && sigp == sig.length()) 106 return t; 107 Type superclass = t; 108 List<Type> superinterfaces = null; 109 while (sigp < sig.length()) { 110 if (superinterfaces == null) 111 superinterfaces = new ArrayList<Type>(); 112 superinterfaces.add(parseTypeSignature()); 113 } 114 return new ClassSigType(typeParamTypes, superclass, superinterfaces); 115 116 } 117 } 118 parseTypeSignature()119 private Type parseTypeSignature() { 120 switch (sig.charAt(sigp)) { 121 case 'B': 122 sigp++; 123 return new SimpleType("byte"); 124 125 case 'C': 126 sigp++; 127 return new SimpleType("char"); 128 129 case 'D': 130 sigp++; 131 return new SimpleType("double"); 132 133 case 'F': 134 sigp++; 135 return new SimpleType("float"); 136 137 case 'I': 138 sigp++; 139 return new SimpleType("int"); 140 141 case 'J': 142 sigp++; 143 return new SimpleType("long"); 144 145 case 'L': 146 return parseClassTypeSignature(); 147 148 case 'S': 149 sigp++; 150 return new SimpleType("short"); 151 152 case 'T': 153 return parseTypeVariableSignature(); 154 155 case 'V': 156 sigp++; 157 return new SimpleType("void"); 158 159 case 'Z': 160 sigp++; 161 return new SimpleType("boolean"); 162 163 case '[': 164 sigp++; 165 return new ArrayType(parseTypeSignature()); 166 167 case '*': 168 sigp++; 169 return new WildcardType(); 170 171 case '+': 172 sigp++; 173 return new WildcardType(WildcardType.Kind.EXTENDS, parseTypeSignature()); 174 175 case '-': 176 sigp++; 177 return new WildcardType(WildcardType.Kind.SUPER, parseTypeSignature()); 178 179 default: 180 throw new IllegalStateException(debugInfo()); 181 } 182 } 183 parseTypeSignatures(char term)184 private List<Type> parseTypeSignatures(char term) { 185 sigp++; 186 List<Type> types = new ArrayList<Type>(); 187 while (sig.charAt(sigp) != term) 188 types.add(parseTypeSignature()); 189 sigp++; 190 return types; 191 } 192 parseClassTypeSignature()193 private Type parseClassTypeSignature() { 194 assert sig.charAt(sigp) == 'L'; 195 sigp++; 196 return parseClassTypeSignatureRest(); 197 } 198 parseClassTypeSignatureRest()199 private Type parseClassTypeSignatureRest() { 200 StringBuilder sb = new StringBuilder(); 201 List<Type> argTypes = null; 202 ClassType t = null; 203 char sigch ; 204 205 do { 206 switch (sigch = sig.charAt(sigp)) { 207 case '<': 208 argTypes = parseTypeSignatures('>'); 209 break; 210 211 case '.': 212 case ';': 213 sigp++; 214 t = new ClassType(t, sb.toString(), argTypes); 215 sb.setLength(0); 216 argTypes = null; 217 break; 218 219 default: 220 sigp++; 221 sb.append(sigch); 222 break; 223 } 224 } while (sigch != ';'); 225 226 return t; 227 } 228 parseTypeParamTypes()229 private List<TypeParamType> parseTypeParamTypes() { 230 assert sig.charAt(sigp) == '<'; 231 sigp++; 232 List<TypeParamType> types = new ArrayList<TypeParamType>(); 233 while (sig.charAt(sigp) != '>') 234 types.add(parseTypeParamType()); 235 sigp++; 236 return types; 237 } 238 parseTypeParamType()239 private TypeParamType parseTypeParamType() { 240 int sep = sig.indexOf(":", sigp); 241 String name = sig.substring(sigp, sep); 242 Type classBound = null; 243 List<Type> interfaceBounds = null; 244 sigp = sep + 1; 245 if (sig.charAt(sigp) != ':') 246 classBound = parseTypeSignature(); 247 while (sig.charAt(sigp) == ':') { 248 sigp++; 249 if (interfaceBounds == null) 250 interfaceBounds = new ArrayList<Type>(); 251 interfaceBounds.add(parseTypeSignature()); 252 } 253 return new TypeParamType(name, classBound, interfaceBounds); 254 } 255 parseTypeVariableSignature()256 private Type parseTypeVariableSignature() { 257 sigp++; 258 int sep = sig.indexOf(';', sigp); 259 Type t = new SimpleType(sig.substring(sigp, sep)); 260 sigp = sep + 1; 261 return t; 262 } 263 debugInfo()264 private String debugInfo() { 265 return sig.substring(0, sigp) + "!" + sig.charAt(sigp) + "!" + sig.substring(sigp+1); 266 } 267 268 private String sig; 269 private int sigp; 270 271 private Type type; 272 } 273