001: package org.aspectj.apache.bcel.classfile;
002:
003: /* ====================================================================
004: * The Apache Software License, Version 1.1
005: *
006: * Copyright (c) 2001 The Apache Software Foundation. All rights
007: * reserved.
008: *
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution,
022: * if any, must include the following acknowledgment:
023: * "This product includes software developed by the
024: * Apache Software Foundation (http://www.apache.org/)."
025: * Alternately, this acknowledgment may appear in the software itself,
026: * if and wherever such third-party acknowledgments normally appear.
027: *
028: * 4. The names "Apache" and "Apache Software Foundation" and
029: * "Apache BCEL" must not be used to endorse or promote products
030: * derived from this software without prior written permission. For
031: * written permission, please contact apache@apache.org.
032: *
033: * 5. Products derived from this software may not be called "Apache",
034: * "Apache BCEL", nor may "Apache" appear in their name, without
035: * prior written permission of the Apache Software Foundation.
036: *
037: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
038: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
039: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
040: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
041: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
042: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
043: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
044: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
045: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
046: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
047: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
048: * SUCH DAMAGE.
049: * ====================================================================
050: *
051: * This software consists of voluntary contributions made by many
052: * individuals on behalf of the Apache Software Foundation. For more
053: * information on the Apache Software Foundation, please see
054: * <http://www.apache.org/>.
055: */
056:
057: import org.apache.bcel.Constants;
058: import java.io.*;
059:
060: /**
061: * This class is derived from <em>Attribute</em> and represents a reference to
062: * a <href="http://wwwipd.ira.uka.de/~pizza/gj/">GJ</a> attribute.
063: *
064: * @version $Id: Signature.java,v 1.2 2006-07-05 15:22:56 ebruneton Exp $
065: * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
066: * @see Attribute
067: */
068: public final class Signature extends Attribute {
069: private int signature_index;
070:
071: /**
072: * Initialize from another object. Note that both objects use the same
073: * references (shallow copy). Use clone() for a physical copy.
074: *
075: * @param c
076: */
077: public Signature(final Signature c) {
078: this (c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c
079: .getConstantPool());
080: }
081:
082: /**
083: * Construct object from file stream.
084: *
085: * @param name_index Index in constant pool to CONSTANT_Utf8
086: * @param length Content length in bytes
087: * @param file Input stream
088: * @param constant_pool Array of constants
089: * @throws IOException
090: */
091: Signature(final int name_index, final int length,
092: final DataInputStream file, final ConstantPool constant_pool)
093: throws IOException {
094: this (name_index, length, file.readUnsignedShort(),
095: constant_pool);
096: }
097:
098: /**
099: * @param name_index Index in constant pool to CONSTANT_Utf8
100: * @param length Content length in bytes
101: * @param constant_pool Array of constants
102: * @param signature_index Index in constant pool to CONSTANT_Utf8
103: */
104: public Signature(final int name_index, final int length,
105: final int signature_index, final ConstantPool constant_pool) {
106: super (Constants.ATTR_SIGNATURE, name_index, length,
107: constant_pool);
108: this .signature_index = signature_index;
109: }
110:
111: /**
112: * Called by objects that are traversing the nodes of the tree implicitely
113: * defined by the contents of a Java class. I.e., the hierarchy of methods,
114: * fields, attributes, etc. spawns a tree of objects.
115: *
116: * @param v Visitor object
117: */
118: public void accept(final Visitor v) {
119: // System.err.println("Visiting non-standard Signature object");
120: // v.visitSignature(this);
121: }
122:
123: /**
124: * Dump source file attribute to file stream in binary format.
125: *
126: * @param file Output file stream
127: * @throws IOException
128: */
129: public final void dump(final DataOutputStream file)
130: throws IOException {
131: super .dump(file);
132: file.writeShort(signature_index);
133: }
134:
135: /**
136: * @return Index in constant pool of source file name.
137: */
138: public final int getSignatureIndex() {
139: return signature_index;
140: }
141:
142: /**
143: * @param signature_index
144: */
145: public final void setSignatureIndex(final int signature_index) {
146: this .signature_index = signature_index;
147: }
148:
149: /**
150: * @return GJ signature.
151: */
152: public final String getSignature() {
153: ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(
154: signature_index, Constants.CONSTANT_Utf8);
155: return c.getBytes();
156: }
157:
158: /**
159: * Extends ByteArrayInputStream to make 'unreading' chars possible.
160: */
161: private static final class MyByteArrayInputStream extends
162: ByteArrayInputStream {
163: MyByteArrayInputStream(final String data) {
164: super (data.getBytes());
165: }
166:
167: final int mark() {
168: return pos;
169: }
170:
171: final String getData() {
172: return new String(buf);
173: }
174:
175: final void reset(final int p) {
176: pos = p;
177: }
178:
179: final void unread() {
180: if (pos > 0) {
181: pos--;
182: }
183: }
184: }
185:
186: private static boolean identStart(final int ch) {
187: return ch == 'T' || ch == 'L';
188: }
189:
190: // private static boolean identPart(int ch) {
191: // return ch == '/' || ch == ';';
192: // }
193:
194: private static final void matchIdent(
195: final MyByteArrayInputStream in, final StringBuffer buf) {
196: int ch;
197:
198: if ((ch = in.read()) == -1) {
199: throw new RuntimeException("Illegal signature: "
200: + in.getData() + " no ident, reaching EOF");
201: }
202:
203: // System.out.println("return from ident:" + (char)ch);
204:
205: if (!identStart(ch)) {
206: StringBuffer buf2 = new StringBuffer();
207:
208: int count = 1;
209: while (Character.isJavaIdentifierPart((char) ch)) {
210: buf2.append((char) ch);
211: count++;
212: ch = in.read();
213: }
214:
215: if (ch == ':') { // Ok, formal parameter
216: in.skip("Ljava/lang/Object".length());
217: buf.append(buf2);
218:
219: ch = in.read();
220: in.unread();
221: // System.out.println("so far:" + buf2 + ":next:" +(char)ch);
222: } else {
223: for (int i = 0; i < count; i++) {
224: in.unread();
225: }
226: }
227:
228: return;
229: }
230:
231: StringBuffer buf2 = new StringBuffer();
232: ch = in.read();
233:
234: do {
235: buf2.append((char) ch);
236: ch = in.read();
237: // System.out.println("within ident:"+ (char)ch);
238:
239: } while (ch != -1
240: && (Character.isJavaIdentifierPart((char) ch) || ch == '/'));
241:
242: buf.append(buf2.toString().replace('/', '.'));
243:
244: // System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
245:
246: if (ch != -1) {
247: in.unread();
248: }
249: }
250:
251: private static final void matchGJIdent(
252: final MyByteArrayInputStream in, final StringBuffer buf) {
253: int ch;
254:
255: matchIdent(in, buf);
256:
257: ch = in.read();
258: if (ch == '<' || ch == '(') { // Parameterized or method
259: // System.out.println("Enter <");
260: buf.append((char) ch);
261: matchGJIdent(in, buf);
262:
263: while ((ch = in.read()) != '>' && ch != ')') { // List of
264: // parameters
265: if (ch == -1) {
266: throw new RuntimeException("Illegal signature: "
267: + in.getData() + " reaching EOF");
268: }
269:
270: // System.out.println("Still no >");
271: buf.append(", ");
272: in.unread();
273: matchGJIdent(in, buf); // Recursive call
274: }
275:
276: // System.out.println("Exit >");
277:
278: buf.append((char) ch);
279: } else {
280: in.unread();
281: }
282:
283: ch = in.read();
284: if (identStart(ch)) {
285: in.unread();
286: matchGJIdent(in, buf);
287: } else if (ch == ')') {
288: in.unread();
289: return;
290: } else if (ch != ';') {
291: throw new RuntimeException("Illegal signature: "
292: + in.getData() + " read " + (char) ch);
293: }
294: }
295:
296: public static String translate(final String s) {
297: // System.out.println("Sig:" + s);
298: StringBuffer buf = new StringBuffer();
299:
300: matchGJIdent(new MyByteArrayInputStream(s), buf);
301:
302: return buf.toString();
303: }
304:
305: public static final boolean isFormalParameterList(final String s) {
306: return s.startsWith("<") && s.indexOf(':') > 0;
307: }
308:
309: public static final boolean isActualParameterList(final String s) {
310: return s.startsWith("L") && s.endsWith(">;");
311: }
312:
313: /**
314: * @return String representation
315: */
316: public final String toString() {
317: String s = getSignature();
318:
319: return "Signature(" + s + ")";
320: }
321:
322: /**
323: * @param constant_pool
324: * @return deep copy of this attribute
325: */
326: public Attribute copy(final ConstantPool constant_pool) {
327: return (Signature) clone();
328: }
329: }
|