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
027 package com.sun.tools.classfile;
028
029 import java.io.IOException;
030
031 /**
032 * See JVMS3, section 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 Descriptor {
040 public class InvalidDescriptor extends DescriptorException {
041 private static final long serialVersionUID = 1L;
042 InvalidDescriptor(String desc) {
043 this.desc = desc;
044 this.index = -1;
045 }
046
047 InvalidDescriptor(String desc, int index) {
048 this.desc = desc;
049 this.index = index;
050 }
051
052 @Override
053 public String getMessage() {
054 // i18n
055 if (index == -1)
056 return "invalid descriptor \"" + desc + "\"";
057 else
058 return "descriptor is invalid at offset " + index + " in \"" + desc + "\"";
059 }
060
061 public final String desc;
062 public final int index;
063
064 }
065
066 public Descriptor(ClassReader cr) throws IOException {
067 this(cr.readUnsignedShort());
068 }
069
070 public Descriptor(int index) {
071 this.index = index;
072
073 }
074
075 public String getValue(ConstantPool constant_pool) throws ConstantPoolException {
076 return constant_pool.getUTF8Value(index);
077 }
078
079 public int getParameterCount(ConstantPool constant_pool)
080 throws ConstantPoolException, InvalidDescriptor {
081 String desc = getValue(constant_pool);
082 int end = desc.indexOf(")");
083 if (end == -1)
084 throw new InvalidDescriptor(desc);
085 parse(desc, 0, end + 1);
086 return count;
087
088 }
089
090 public String getParameterTypes(ConstantPool constant_pool)
091 throws ConstantPoolException, InvalidDescriptor {
092 String desc = getValue(constant_pool);
093 int end = desc.indexOf(")");
094 if (end == -1)
095 throw new InvalidDescriptor(desc);
096 return parse(desc, 0, end + 1);
097 }
098
099 public String getReturnType(ConstantPool constant_pool)
100 throws ConstantPoolException, InvalidDescriptor {
101 String desc = getValue(constant_pool);
102 int end = desc.indexOf(")");
103 if (end == -1)
104 throw new InvalidDescriptor(desc);
105 return parse(desc, end + 1, desc.length());
106 }
107
108 public String getFieldType(ConstantPool constant_pool)
109 throws ConstantPoolException, InvalidDescriptor {
110 String desc = getValue(constant_pool);
111 return parse(desc, 0, desc.length());
112 }
113
114 private String parse(String desc, int start, int end)
115 throws InvalidDescriptor {
116 int p = start;
117 StringBuffer sb = new StringBuffer();
118 int dims = 0;
119 count = 0;
120
121 while (p < end) {
122 String type;
123 char ch;
124 switch (ch = desc.charAt(p++)) {
125 case '(':
126 sb.append('(');
127 continue;
128
129 case ')':
130 sb.append(')');
131 continue;
132
133 case '[':
134 dims++;
135 continue;
136
137 case 'B':
138 type = "byte";
139 break;
140
141 case 'C':
142 type = "char";
143 break;
144
145 case 'D':
146 type = "double";
147 break;
148
149 case 'F':
150 type = "float";
151 break;
152
153 case 'I':
154 type = "int";
155 break;
156
157 case 'J':
158 type = "long";
159 break;
160
161 case 'L':
162 int sep = desc.indexOf(';', p);
163 if (sep == -1)
164 throw new InvalidDescriptor(desc, p - 1);
165 type = desc.substring(p, sep).replace('/', '.');
166 p = sep + 1;
167 break;
168
169 case 'S':
170 type = "short";
171 break;
172
173 case 'Z':
174 type = "boolean";
175 break;
176
177 case 'V':
178 type = "void";
179 break;
180
181 default:
182 throw new InvalidDescriptor(desc, p - 1);
183 }
184
185 if (sb.length() > 1 && sb.charAt(0) == '(')
186 sb.append(", ");
187 sb.append(type);
188 for ( ; dims > 0; dims-- )
189 sb.append("[]");
190
191 count++;
192 }
193
194 return sb.toString();
195 }
196
197 public final int index;
198 private int count;
199 }