1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.classfile;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.DataInputStream;
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 import org.apache.bcel.Constants;
24
25 /***
26 * This class is derived from <em>Attribute</em> and represents a reference
27 * to a GJ attribute.
28 *
29 * @version $Id: Signature.java 386056 2006-03-15 11:31:56Z tcurdt $
30 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
31 * @see Attribute
32 */
33 public final class Signature extends Attribute {
34
35 private int signature_index;
36
37
38 /***
39 * Initialize from another object. Note that both objects use the same
40 * references (shallow copy). Use clone() for a physical copy.
41 */
42 public Signature(Signature c) {
43 this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
44 }
45
46
47 /***
48 * Construct object from file stream.
49 * @param name_index Index in constant pool to CONSTANT_Utf8
50 * @param length Content length in bytes
51 * @param file Input stream
52 * @param constant_pool Array of constants
53 * @throws IOException
54 */
55 Signature(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
56 throws IOException {
57 this(name_index, length, file.readUnsignedShort(), constant_pool);
58 }
59
60
61 /***
62 * @param name_index Index in constant pool to CONSTANT_Utf8
63 * @param length Content length in bytes
64 * @param signature_index Index in constant pool to CONSTANT_Utf8
65 * @param constant_pool Array of constants
66 */
67 public Signature(int name_index, int length, int signature_index, ConstantPool constant_pool) {
68 super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool);
69 this.signature_index = signature_index;
70 }
71
72
73 /***
74 * Called by objects that are traversing the nodes of the tree implicitely
75 * defined by the contents of a Java class. I.e., the hierarchy of methods,
76 * fields, attributes, etc. spawns a tree of objects.
77 *
78 * @param v Visitor object
79 */
80 public void accept( Visitor v ) {
81
82 v.visitSignature(this);
83 }
84
85
86 /***
87 * Dump source file attribute to file stream in binary format.
88 *
89 * @param file Output file stream
90 * @throws IOException
91 */
92 public final void dump( DataOutputStream file ) throws IOException {
93 super.dump(file);
94 file.writeShort(signature_index);
95 }
96
97
98 /***
99 * @return Index in constant pool of source file name.
100 */
101 public final int getSignatureIndex() {
102 return signature_index;
103 }
104
105
106 /***
107 * @param signature_index the index info the constant pool of this signature
108 */
109 public final void setSignatureIndex( int signature_index ) {
110 this.signature_index = signature_index;
111 }
112
113
114 /***
115 * @return GJ signature.
116 */
117 public final String getSignature() {
118 ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(signature_index,
119 Constants.CONSTANT_Utf8);
120 return c.getBytes();
121 }
122
123 /***
124 * Extends ByteArrayInputStream to make 'unreading' chars possible.
125 */
126 private static final class MyByteArrayInputStream extends ByteArrayInputStream {
127
128 MyByteArrayInputStream(String data) {
129 super(data.getBytes());
130 }
131
132
133 final int mark() {
134 return pos;
135 }
136
137
138 final String getData() {
139 return new String(buf);
140 }
141
142
143 final void reset( int p ) {
144 pos = p;
145 }
146
147
148 final void unread() {
149 if (pos > 0) {
150 pos--;
151 }
152 }
153 }
154
155
156 private static boolean identStart( int ch ) {
157 return ch == 'T' || ch == 'L';
158 }
159
160
161 private static final void matchIdent( MyByteArrayInputStream in, StringBuffer buf ) {
162 int ch;
163 if ((ch = in.read()) == -1) {
164 throw new RuntimeException("Illegal signature: " + in.getData()
165 + " no ident, reaching EOF");
166 }
167
168 if (!identStart(ch)) {
169 StringBuffer buf2 = new StringBuffer();
170 int count = 1;
171 while (Character.isJavaIdentifierPart((char) ch)) {
172 buf2.append((char) ch);
173 count++;
174 ch = in.read();
175 }
176 if (ch == ':') {
177 in.skip("Ljava/lang/Object".length());
178 buf.append(buf2);
179 ch = in.read();
180 in.unread();
181
182 } else {
183 for (int i = 0; i < count; i++) {
184 in.unread();
185 }
186 }
187 return;
188 }
189 StringBuffer buf2 = new StringBuffer();
190 ch = in.read();
191 do {
192 buf2.append((char) ch);
193 ch = in.read();
194
195 } while ((ch != -1) && (Character.isJavaIdentifierPart((char) ch) || (ch == '/')));
196 buf.append(buf2.toString().replace('/', '.'));
197
198 if (ch != -1) {
199 in.unread();
200 }
201 }
202
203
204 private static final void matchGJIdent( MyByteArrayInputStream in, StringBuffer buf ) {
205 int ch;
206 matchIdent(in, buf);
207 ch = in.read();
208 if ((ch == '<') || ch == '(') {
209
210 buf.append((char) ch);
211 matchGJIdent(in, buf);
212 while (((ch = in.read()) != '>') && (ch != ')')) {
213 if (ch == -1) {
214 throw new RuntimeException("Illegal signature: " + in.getData()
215 + " reaching EOF");
216 }
217
218 buf.append(", ");
219 in.unread();
220 matchGJIdent(in, buf);
221 }
222
223 buf.append((char) ch);
224 } else {
225 in.unread();
226 }
227 ch = in.read();
228 if (identStart(ch)) {
229 in.unread();
230 matchGJIdent(in, buf);
231 } else if (ch == ')') {
232 in.unread();
233 return;
234 } else if (ch != ';') {
235 throw new RuntimeException("Illegal signature: " + in.getData() + " read " + (char) ch);
236 }
237 }
238
239
240 public static String translate( String s ) {
241
242 StringBuffer buf = new StringBuffer();
243 matchGJIdent(new MyByteArrayInputStream(s), buf);
244 return buf.toString();
245 }
246
247
248 public static final boolean isFormalParameterList( String s ) {
249 return s.startsWith("<") && (s.indexOf(':') > 0);
250 }
251
252
253 public static final boolean isActualParameterList( String s ) {
254 return s.startsWith("L") && s.endsWith(">;");
255 }
256
257
258 /***
259 * @return String representation
260 */
261 public final String toString() {
262 String s = getSignature();
263 return "Signature(" + s + ")";
264 }
265
266
267 /***
268 * @return deep copy of this attribute
269 */
270 public Attribute copy( ConstantPool _constant_pool ) {
271 return (Signature) clone();
272 }
273 }