+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005 Contributors.
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Adrian Colyer Initial implementation
- * ******************************************************************/
-package org.aspectj.apache.bcel.classfile;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.aspectj.apache.bcel.classfile.Signature.ArrayTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.ClassTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.FieldTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.FormalTypeParameter;
-import org.aspectj.apache.bcel.classfile.Signature.MethodTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.SimpleClassTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.TypeArgument;
-import org.aspectj.apache.bcel.classfile.Signature.TypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.TypeVariableSignature;
-import org.aspectj.apache.bcel.classfile.Signature.BaseTypeSignature;
-
-/**
- * Parses the generic signature attribute as defined in the JVM spec.
- */
-public class GenericSignatureParser {
-
- private String inputString;
- private String[] tokenStream; // for parse in flight
- private int tokenIndex = 0;
-
- /**
- * AMC.
- * Parse the signature string interpreting it as a ClassSignature according to
- * the grammar defined in Section 4.4.4 of the JVM specification.
- */
- public Signature.ClassSignature parseAsClassSignature(String sig) {
- this.inputString = sig;
- tokenStream = tokenize(sig);
- tokenIndex = 0;
- Signature.ClassSignature classSig = new Signature.ClassSignature();
- // FormalTypeParameters-opt
- if (maybeEat("<")) {
- List formalTypeParametersList = new ArrayList();
- do {
- formalTypeParametersList.add(parseFormalTypeParameter());
- } while (!maybeEat(">"));
- classSig.formalTypeParameters = new FormalTypeParameter[formalTypeParametersList.size()];
- formalTypeParametersList.toArray(classSig.formalTypeParameters);
- }
- classSig.superclassSignature = parseClassTypeSignature();
- List superIntSigs = new ArrayList();
- while (tokenIndex < tokenStream.length) {
- superIntSigs.add(parseClassTypeSignature());
- }
- classSig.superInterfaceSignatures = new ClassTypeSignature[superIntSigs.size()];
- superIntSigs.toArray(classSig.superInterfaceSignatures);
- return classSig;
- }
-
- /**
- * AMC.
- * Parse the signature string interpreting it as a MethodTypeSignature according to
- * the grammar defined in Section 4.4.4 of the JVM specification.
- */
- public MethodTypeSignature parseAsMethodSignature(String sig) {
- this.inputString = sig;
- tokenStream = tokenize(sig);
- tokenIndex = 0;
- FormalTypeParameter[] formals = new FormalTypeParameter[0];
- TypeSignature returnType = null;
- // FormalTypeParameters-opt
- if (maybeEat("<")) {
- List formalTypeParametersList = new ArrayList();
- do {
- formalTypeParametersList.add(parseFormalTypeParameter());
- } while (!maybeEat(">"));
- formals = new FormalTypeParameter[formalTypeParametersList.size()];
- formalTypeParametersList.toArray(formals);
- }
- // Parameters
- eat("(");
- List paramList = new ArrayList();
- while(!maybeEat(")")) {
- FieldTypeSignature fsig = parseFieldTypeSignature(true);
- if (fsig != null) {
- paramList.add(fsig);
- } else {
- paramList.add(new Signature.BaseTypeSignature(eatIdentifier()));
- }
- }
- TypeSignature[] params = new TypeSignature[paramList.size()];
- paramList.toArray(params);
- // return type
- returnType = parseFieldTypeSignature(true);
- if (returnType == null) returnType = new Signature.BaseTypeSignature(eatIdentifier());
- // throws
- List throwsList = new ArrayList();
- while (maybeEat("^")) {
- FieldTypeSignature fsig = parseFieldTypeSignature(false);
- throwsList.add(fsig);
- }
- FieldTypeSignature[] throwsSigs = new FieldTypeSignature[throwsList.size()];
- throwsList.toArray(throwsSigs);
- return new Signature.MethodTypeSignature(formals,params,returnType,throwsSigs);
- }
-
- /**
- * AMC.
- * Parse the signature string interpreting it as a FieldTypeSignature according to
- * the grammar defined in Section 4.4.4 of the JVM specification.
- */
- public FieldTypeSignature parseAsFieldSignature(String sig) {
- this.inputString = sig;
- tokenStream = tokenize(sig);
- tokenIndex = 0;
- return parseFieldTypeSignature(false);
- }
-
- private FormalTypeParameter parseFormalTypeParameter() {
- FormalTypeParameter ftp = new FormalTypeParameter();
- // Identifier
- ftp.identifier = eatIdentifier();
- // ClassBound
- eat(":");
- ftp.classBound = parseFieldTypeSignature(true);
- if (ftp.classBound == null) {
- ftp.classBound = new ClassTypeSignature("Ljava/lang/Object;","Ljava/lang/Object");
- }
- // Optional InterfaceBounds
- List optionalBounds = new ArrayList();
- while (maybeEat(":")) {
- optionalBounds.add(parseFieldTypeSignature(false));
- }
- ftp.interfaceBounds = new FieldTypeSignature[optionalBounds.size()];
- optionalBounds.toArray(ftp.interfaceBounds);
- return ftp;
- }
-
- private FieldTypeSignature parseFieldTypeSignature(boolean isOptional) {
- if (isOptional) {
- // anything other than 'L', 'T' or '[' and we're out of here
- if (!tokenStream[tokenIndex].startsWith("L") &&
- !tokenStream[tokenIndex].startsWith("T") &&
- !tokenStream[tokenIndex].startsWith("[")) {
- return null;
- }
- }
- if (maybeEat("[")) {
- return parseArrayTypeSignature();
- } else if (tokenStream[tokenIndex].startsWith("L")) {
- return parseClassTypeSignature();
- } else if (tokenStream[tokenIndex].startsWith("T")) {
- return parseTypeVariableSignature();
- } else {
- throw new IllegalStateException("Expecting [,L, or T, but found " +
- tokenStream[tokenIndex] + " while unpacking " + inputString);
- }
- }
-
- private ArrayTypeSignature parseArrayTypeSignature() {
- // opening [ already eaten
- FieldTypeSignature fieldType = parseFieldTypeSignature(true);
- if (fieldType != null) {
- return new ArrayTypeSignature(fieldType);
- } else {
- // must be BaseType array
- return new ArrayTypeSignature(new BaseTypeSignature(eatIdentifier()));
- }
- }
-
- // L PackageSpecifier* SimpleClassTypeSignature ClassTypeSignature* ;
- private ClassTypeSignature parseClassTypeSignature() {
- SimpleClassTypeSignature outerType = null;
- SimpleClassTypeSignature[] nestedTypes = new SimpleClassTypeSignature[0];
- StringBuffer ret = new StringBuffer();
- String identifier = eatIdentifier();
- ret.append(identifier);
- while (maybeEat("/")) {
- ret.append("/"); // dont forget this...
- ret.append(eatIdentifier());
- }
- identifier = ret.toString();
- // now we have either a "." indicating the start of a nested type,
- // or a "<" indication type arguments, or ";" and we are done.
- while (!maybeEat(";")) {
- if (maybeEat(".")) {
- // outer type completed
- outerType = new SimpleClassTypeSignature(identifier);
- List nestedTypeList = new ArrayList();
- do {
- ret.append(".");
- SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
- ret.append(sig.toString());
- nestedTypeList.add(sig);
- } while(maybeEat("."));
- nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
- nestedTypeList.toArray(nestedTypes);
- } else if (tokenStream[tokenIndex].equals("<")) {
- ret.append("<");
- TypeArgument[] tArgs = maybeParseTypeArguments();
- for (int i=0; i < tArgs.length; i++) {
- ret.append(tArgs[i].toString());
- }
- ret.append(">");
- outerType = new SimpleClassTypeSignature(identifier,tArgs);
- // now parse possible nesteds...
- List nestedTypeList = new ArrayList();
- while (maybeEat(".")) {
- ret.append(".");
- SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
- ret.append(sig.toString());
- nestedTypeList.add(sig);
- }
- nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
- nestedTypeList.toArray(nestedTypes);
- } else {
- throw new IllegalStateException("Expecting .,<, or ;, but found " + tokenStream[tokenIndex] + " while unpacking " + inputString);
- }
- }
- ret.append(";");
- if (outerType == null) outerType = new SimpleClassTypeSignature(ret.toString());
- return new ClassTypeSignature(ret.toString(),outerType,nestedTypes);
- }
-
- private SimpleClassTypeSignature parseSimpleClassTypeSignature() {
- String identifier = eatIdentifier();
- TypeArgument[] tArgs = maybeParseTypeArguments();
- if (tArgs != null) {
- return new SimpleClassTypeSignature(identifier,tArgs);
- } else {
- return new SimpleClassTypeSignature(identifier);
- }
- }
-
- private TypeArgument parseTypeArgument() {
- boolean isPlus = false;
- boolean isMinus = false;
- if (maybeEat("*")) {
- return new TypeArgument();
- } else if (maybeEat("+")) {
- isPlus = true;
- } else if (maybeEat("-")) {
- isMinus = true;
- }
- FieldTypeSignature sig = parseFieldTypeSignature(false);
- return new TypeArgument(isPlus,isMinus,sig);
- }
-
- private TypeArgument[] maybeParseTypeArguments() {
- if (maybeEat("<")) {
- List typeArgs = new ArrayList();
- do {
- TypeArgument arg = parseTypeArgument();
- typeArgs.add(arg);
- } while(!maybeEat(">"));
- TypeArgument[] tArgs = new TypeArgument[typeArgs.size()];
- typeArgs.toArray(tArgs);
- return tArgs;
- } else {
- return null;
- }
- }
-
- private TypeVariableSignature parseTypeVariableSignature() {
- TypeVariableSignature tv = new TypeVariableSignature(eatIdentifier());
- eat(";");
- return tv;
- }
-
- private boolean maybeEat(String token) {
- if (tokenStream.length <= tokenIndex) return false;
- if (tokenStream[tokenIndex].equals(token)) {
- tokenIndex++;
- return true;
- }
- return false;
- }
-
- private void eat(String token) {
- if (!tokenStream[tokenIndex].equals(token)) {
- throw new IllegalStateException("Expecting " + token + " but found " + tokenStream[tokenIndex] + " while unpacking " + inputString);
- }
- tokenIndex++;
- }
-
- private String eatIdentifier() {
- return tokenStream[tokenIndex++];
- }
-
- /**
- * non-private for test visibility
- * Splits a string containing a generic signature into tokens for consumption
- * by the parser.
- */
- public String[] tokenize(String signatureString) {
- char[] chars = signatureString.toCharArray();
- int index = 0;
- List tokens = new ArrayList();
- StringBuffer identifier = new StringBuffer();
- boolean inParens = false;
- boolean inArray = false;
- boolean couldSeePrimitive = false;
- do {
- switch (chars[index]) {
- case '<' :
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add("<");
- break;
- case '>' :
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add(">");
- break;
- case ':' :
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add(":");
- break;
- case '/' :
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add("/");
- couldSeePrimitive = false;
- break;
- case ';' :
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add(";");
- couldSeePrimitive = true;
- inArray = false;
- break;
- case '^':
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- tokens.add("^");
- break;
- case '+':
- tokens.add("+");
- break;
- case '-':
- tokens.add("-");
- break;
- case '*':
- tokens.add("*");
- break;
- case '.' :
- if (identifier.length() > 0) tokens.add(identifier.toString());
- identifier = new StringBuffer();
- couldSeePrimitive = false;
- tokens.add(".");
- break;
- case '(' :
- tokens.add("(");
- inParens = true;
- couldSeePrimitive = true;
- break;
- case ')' :
- tokens.add(")");
- inParens = false;
- break;
- case '[' :
- tokens.add("[");
- couldSeePrimitive = true;
- inArray = true;
- break;
- case 'B' :
- case 'C' :
- case 'D' :
- case 'F' :
- case 'I' :
- case 'J' :
- case 'S' :
- case 'V' :
- case 'Z' :
- if ((inParens || inArray) && couldSeePrimitive && identifier.length() == 0) {
- tokens.add(new String("" + chars[index]));
- } else {
- identifier.append(chars[index]);
- }
- inArray = false;
- break;
- case 'L' :
- couldSeePrimitive = false;
- // deliberate fall-through
- default :
- identifier.append(chars[index]);
- }
- } while((++index) < chars.length);
- if (identifier.length() > 0) tokens.add(identifier.toString());
- String [] tokenArray = new String[tokens.size()];
- tokens.toArray(tokenArray);
- return tokenArray;
- }
-
-}
* The intent of this class is to represent a parsed or otherwise existing class file. Those interested in programatically
* generating classes should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
*
- * @version $Id: JavaClass.java,v 1.13 2008/08/28 15:36:59 aclement Exp $
+ * @version $Id: JavaClass.java,v 1.14 2008/10/20 18:31:01 aclement Exp $
* @see org.aspectj.apache.bcel.generic.ClassGen
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
*/
}
}
- /**
- * the parsed version of the above
- */
- public final Signature.ClassSignature getGenericClassTypeSignature() {
+ public final Signature getSignatureAttribute() {
loadGenericSignatureInfoIfNecessary();
- if (signatureAttribute != null) {
- return signatureAttribute.asClassSignature();
- }
- return null;
+ return signatureAttribute;
}
}
* attribute
*/
-
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import org.aspectj.apache.bcel.Constants;
/**
- * This class is derived from <em>Attribute</em> and represents a reference
- * to a <href="http://wwwipd.ira.uka.de/~pizza/gj/">GJ</a> attribute.
- *
- * @version $Id: Signature.java,v 1.8 2008/08/26 15:01:23 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- * @see Attribute
+ * This class is derived from <em>Attribute</em> and represents a reference to a <href="http://wwwipd.ira.uka.de/~pizza/gj/">GJ</a>
+ * attribute.
+ *
+ * @version $Id: Signature.java,v 1.9 2008/10/20 18:31:01 aclement Exp $
+ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
+ * @see Attribute
*/
public final class Signature extends Attribute {
- private int signature_index;
-
- /**
- * Initialize from another object. Note that both objects use the same
- * references (shallow copy). Use clone() for a physical copy.
- */
- public Signature(Signature c) {
- this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
- }
-
- /**
- * Construct object from file stream.
- * @param name_index Index in constant pool to CONSTANT_Utf8
- * @param length Content length in bytes
- * @param file Input stream
- * @param constant_pool Array of constants
- * @throws IOException
- */
- Signature(int name_index, int length, DataInputStream file,
- ConstantPool constant_pool) throws IOException
- {
- this(name_index, length, file.readUnsignedShort(), constant_pool);
- }
-
- /**
- * @param name_index Index in constant pool to CONSTANT_Utf8
- * @param length Content length in bytes
- * @param constant_pool Array of constants
- * @param Signature_index Index in constant pool to CONSTANT_Utf8
- */
- public Signature(int name_index, int length, int signature_index,
- ConstantPool constant_pool)
- {
- super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool);
- this.signature_index = signature_index;
- }
-
- /**
- * Called by objects that are traversing the nodes of the tree implicitely
- * defined by the contents of a Java class. I.e., the hierarchy of methods,
- * fields, attributes, etc. spawns a tree of objects.
- *
- * @param v Visitor object
- */
- public void accept(ClassVisitor v) {
- System.err.println("Visiting non-standard Signature object");
- v.visitSignature(this);
- }
-
- /**
- * Dump source file attribute to file stream in binary format.
- *
- * @param file Output file stream
- * @throws IOException
- */
- public final void dump(DataOutputStream file) throws IOException
- {
- super.dump(file);
- file.writeShort(signature_index);
- }
-
- /**
- * @return Index in constant pool of source file name.
- */
- public final int getSignatureIndex() { return signature_index; }
-
- /**
- * @param Signature_index.
- */
- public final void setSignatureIndex(int signature_index) {
- this.signature_index = signature_index;
- }
-
- /**
- * @return GJ signature.
- */
- public final String getSignature() {
- ConstantUtf8 c = (ConstantUtf8)constantPool.getConstant(signature_index,
- Constants.CONSTANT_Utf8);
- return c.getBytes();
- }
-
- /**
- * Extends ByteArrayInputStream to make 'unreading' chars possible.
- */
- private static final class MyByteArrayInputStream extends ByteArrayInputStream {
- MyByteArrayInputStream(String data) { super(data.getBytes()); }
- final int mark() { return pos; }
- final String getData() { return new String(buf); }
- final void reset(int p) { pos = p; }
- final void unread() { if(pos > 0) pos--; }
- }
-
- private static boolean identStart(int ch) {
- return ch == 'T' || ch == 'L';
- }
-
- private static final void matchIdent(MyByteArrayInputStream in, StringBuffer buf) {
- int ch;
-
- if((ch = in.read()) == -1)
- throw new RuntimeException("Illegal signature: " + in.getData() +
- " no ident, reaching EOF");
-
- //System.out.println("return from ident:" + (char)ch);
-
- if(!identStart(ch)) {
- StringBuffer buf2 = new StringBuffer();
-
- int count = 1;
- while(Character.isJavaIdentifierPart((char)ch)) {
- buf2.append((char)ch);
- count++;
- ch = in.read();
- }
-
- if(ch == ':') { // Ok, formal parameter
- in.skip("Ljava/lang/Object".length());
- buf.append(buf2);
-
- ch = in.read();
- in.unread();
- //System.out.println("so far:" + buf2 + ":next:" +(char)ch);
- } else {
- for(int i=0; i < count; i++)
- in.unread();
- }
-
- return;
- }
-
- StringBuffer buf2 = new StringBuffer();
- ch = in.read();
-
- do {
- buf2.append((char)ch);
- ch = in.read();
- //System.out.println("within ident:"+ (char)ch);
-
- } while((ch != -1) && (Character.isJavaIdentifierPart((char)ch) || (ch == '/')));
-
- buf.append(buf2.toString().replace('/', '.'));
-
- //System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
-
- if(ch != -1)
- in.unread();
- }
-
- private static final void matchGJIdent(MyByteArrayInputStream in,
- StringBuffer buf)
- {
- int ch;
-
- matchIdent(in, buf);
-
- ch = in.read();
- if((ch == '<') || ch == '(') { // Parameterized or method
- //System.out.println("Enter <");
- buf.append((char)ch);
- matchGJIdent(in, buf);
-
- while(((ch = in.read()) != '>') && (ch != ')')) { // List of parameters
- if(ch == -1)
- throw new RuntimeException("Illegal signature: " + in.getData() +
- " reaching EOF");
-
- //System.out.println("Still no >");
- buf.append(", ");
- in.unread();
- matchGJIdent(in, buf); // Recursive call
- }
-
- //System.out.println("Exit >");
-
- buf.append((char)ch);
- } else
- in.unread();
-
- ch = in.read();
- if(identStart(ch)) {
- in.unread();
- matchGJIdent(in, buf);
- } else if(ch == ')') {
- in.unread();
- return;
- } else if(ch != ';')
- throw new RuntimeException("Illegal signature: " + in.getData() + " read " +
- (char)ch);
- }
-
- public static String translate(String s) {
- //System.out.println("Sig:" + s);
- StringBuffer buf = new StringBuffer();
-
- matchGJIdent(new MyByteArrayInputStream(s), buf);
-
- return buf.toString();
- }
-
- public static final boolean isFormalParameterList(String s) {
- return s.startsWith("<") && (s.indexOf(':') > 0);
- }
-
- public static final boolean isActualParameterList(String s) {
- return s.startsWith("L") && s.endsWith(">;");
- }
-
- /**
- * @return String representation
- */
- public final String toString() {
- String s = getSignature();
-
- return "Signature(" + s + ")";
- }
-
- /**
- * @return deep copy of this attribute
- */
- public Attribute copy(ConstantPool constant_pool) {
- return (Signature)clone();
- }
-
- // =============================================
- // AMC extensions
-
- private ClassSignature classSig;
- private MethodTypeSignature methodSig;
- private FieldTypeSignature fieldSig;
-
- public ClassSignature asClassSignature() {
- if (classSig == null) {
- GenericSignatureParser parser = new GenericSignatureParser();
- classSig = parser.parseAsClassSignature(getSignature());
- }
- return classSig;
- }
-
- public MethodTypeSignature asMethodTypeSignature() {
- if (methodSig == null) {
- GenericSignatureParser parser = new GenericSignatureParser();
- methodSig = parser.parseAsMethodSignature(getSignature());
- }
- return methodSig;
- }
-
- public FieldTypeSignature asFieldTypeSignature() {
- if (fieldSig == null) {
- GenericSignatureParser parser = new GenericSignatureParser();
- fieldSig = parser.parseAsFieldSignature(getSignature());
- }
- return fieldSig;
- }
-
- /**
- * structure holding a parsed class signature
- */
- public static class ClassSignature {
- public FormalTypeParameter[] formalTypeParameters = new FormalTypeParameter[0];
- public ClassTypeSignature superclassSignature;
- public ClassTypeSignature[] superInterfaceSignatures = new ClassTypeSignature[0];
- public String toString() {
- StringBuffer ret = new StringBuffer();
- ret.append(formalTypeParameters.toString());
- ret.append(superclassSignature.toString());
- for (int i = 0; i < superInterfaceSignatures.length; i++) {
- ret.append(superInterfaceSignatures[i].toString());
- }
- return ret.toString();
- }
- }
-
- public static class MethodTypeSignature {
- public FormalTypeParameter[] formalTypeParameters = new FormalTypeParameter[0];
- public TypeSignature[] parameters = new TypeSignature[0];
- public TypeSignature returnType;
- public FieldTypeSignature[] throwsSignatures = new FieldTypeSignature[0];
-
- public MethodTypeSignature(
- FormalTypeParameter[] aFormalParameterList,
- TypeSignature[] aParameterList,
- TypeSignature aReturnType,
- FieldTypeSignature[] aThrowsSignatureList
- ) {
- this.formalTypeParameters = aFormalParameterList;
- this.parameters = aParameterList;
- this.returnType = aReturnType;
- this.throwsSignatures = aThrowsSignatureList;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- if (formalTypeParameters.length > 0) {
- sb.append("<");
- for (int i = 0; i < formalTypeParameters.length; i++) {
- sb.append(formalTypeParameters[i].toString());
- }
- sb.append(">");
- }
- sb.append("(");
- for (int i = 0; i < parameters.length; i++) {
- sb.append(parameters[i].toString());
- }
- sb.append(")");
- sb.append(returnType.toString());
- for (int i = 0; i < throwsSignatures.length; i++) {
- sb.append("^");
- sb.append(throwsSignatures[i].toString());
- }
- return sb.toString();
- }
- }
-
- /**
- * structure capturing a FormalTypeParameter from the Signature grammar
- */
- public static class FormalTypeParameter {
- public String identifier;
- public FieldTypeSignature classBound;
- public FieldTypeSignature[] interfaceBounds;
- public String toString() {
- StringBuffer ret = new StringBuffer();
- ret.append("T");
- ret.append(identifier);
- ret.append(":");
- ret.append(classBound.toString());
- for (int i = 0; i < interfaceBounds.length; i++) {
- ret.append(":");
- ret.append(interfaceBounds[i].toString());
- }
- return ret.toString();
- }
- }
-
- public static abstract class TypeSignature {
- public boolean isBaseType() { return false; }
- }
-
- public static class BaseTypeSignature extends TypeSignature {
- private String sig;
- public BaseTypeSignature(String aPrimitiveType) {
- sig = aPrimitiveType;
- }
- public boolean isBaseType() { return true; }
- public String toString() {
- return sig;
- }
- }
-
- public static abstract class FieldTypeSignature extends TypeSignature {
- public boolean isClassTypeSignature() { return false; }
- public boolean isTypeVariableSignature() { return false; }
- public boolean isArrayTypeSignature() { return false; }
- }
-
- public static class ClassTypeSignature extends FieldTypeSignature {
- public String classSignature;
- public SimpleClassTypeSignature outerType;
- public SimpleClassTypeSignature[] nestedTypes;
- public ClassTypeSignature(String sig,String identifier) {
- this.classSignature = sig;
- this.outerType = new SimpleClassTypeSignature(identifier);
- this.nestedTypes = new SimpleClassTypeSignature[0];
- }
- public ClassTypeSignature(String sig, SimpleClassTypeSignature outer, SimpleClassTypeSignature[] inners) {
- this.classSignature = sig;
- this.outerType = outer;
- this.nestedTypes = inners;
- }
- public boolean isClassTypeSignature() { return true; }
-
- public String toString() {
- return classSignature;
- }
- }
-
- public static class TypeVariableSignature extends FieldTypeSignature {
- public String typeVariableName;
- public TypeVariableSignature(String typeVarToken) {
- this.typeVariableName = typeVarToken.substring(1);
- }
- public boolean isTypeVariableSignature() { return true; }
- public String toString() {
- return "T" + typeVariableName + ";";
- }
- }
-
- public static class ArrayTypeSignature extends FieldTypeSignature {
- public TypeSignature typeSig;
- public ArrayTypeSignature(TypeSignature aTypeSig) {
- this.typeSig = aTypeSig;
- }
- public boolean isArrayTypeSignature() { return true; }
- public String toString() {
- return "[" + typeSig.toString();
- }
- }
-
- public static class SimpleClassTypeSignature {
- public String identifier;
- public TypeArgument[] typeArguments;
-
- public SimpleClassTypeSignature(String identifier) {
- this.identifier = identifier;
- this.typeArguments = new TypeArgument[0];
- }
-
- public SimpleClassTypeSignature(String identifier, TypeArgument[] args) {
- this.identifier = identifier;
- this.typeArguments = args;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(identifier);
- if (typeArguments.length > 0) {
- sb.append("<");
- for (int i = 0; i < typeArguments.length; i++) {
- sb.append(typeArguments[i].toString());
- }
- sb.append(">");
- }
- return sb.toString();
- }
- }
-
- public static class TypeArgument {
- public boolean isWildcard = false;
- public boolean isPlus = false;
- public boolean isMinus = false;
- public FieldTypeSignature signature; // null if isWildcard
-
- public TypeArgument() {
- isWildcard = true;
- }
-
- public TypeArgument(boolean plus, boolean minus, FieldTypeSignature aSig) {
- this.isPlus = plus;
- this.isMinus = minus;
- this.signature = aSig;
- }
-
- public String toString() {
- if (isWildcard) return "*";
- StringBuffer sb = new StringBuffer();
- if (isPlus) sb.append("+");
- if (isMinus) sb.append("-");
- sb.append(signature.toString());
- return sb.toString();
- }
- }
-
+ private int signature_index;
+
+ /**
+ * Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a physical
+ * copy.
+ */
+ public Signature(Signature c) {
+ this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
+ }
+
+ /**
+ * Construct object from file stream.
+ *
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ Signature(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException {
+ this(name_index, length, file.readUnsignedShort(), constant_pool);
+ }
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param constant_pool Array of constants
+ * @param Signature_index Index in constant pool to CONSTANT_Utf8
+ */
+ public Signature(int name_index, int length, int signature_index, ConstantPool constant_pool) {
+ super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool);
+ this.signature_index = signature_index;
+ }
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely defined by the contents of a Java class. I.e., the
+ * hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept(ClassVisitor v) {
+ System.err.println("Visiting non-standard Signature object");
+ v.visitSignature(this);
+ }
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump(DataOutputStream file) throws IOException {
+ super.dump(file);
+ file.writeShort(signature_index);
+ }
+
+ /**
+ * @return Index in constant pool of source file name.
+ */
+ public final int getSignatureIndex() {
+ return signature_index;
+ }
+
+ /**
+ * @param Signature_index.
+ */
+ public final void setSignatureIndex(int signature_index) {
+ this.signature_index = signature_index;
+ }
+
+ /**
+ * @return GJ signature.
+ */
+ public final String getSignature() {
+ ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant(signature_index, Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ /**
+ * Extends ByteArrayInputStream to make 'unreading' chars possible.
+ */
+ private static final class MyByteArrayInputStream extends ByteArrayInputStream {
+ MyByteArrayInputStream(String data) {
+ super(data.getBytes());
+ }
+
+ final int mark() {
+ return pos;
+ }
+
+ final String getData() {
+ return new String(buf);
+ }
+
+ final void reset(int p) {
+ pos = p;
+ }
+
+ final void unread() {
+ if (pos > 0)
+ pos--;
+ }
+ }
+
+ private static boolean identStart(int ch) {
+ return ch == 'T' || ch == 'L';
+ }
+
+ private static final void matchIdent(MyByteArrayInputStream in, StringBuffer buf) {
+ int ch;
+
+ if ((ch = in.read()) == -1)
+ throw new RuntimeException("Illegal signature: " + in.getData() + " no ident, reaching EOF");
+
+ // System.out.println("return from ident:" + (char)ch);
+
+ if (!identStart(ch)) {
+ StringBuffer buf2 = new StringBuffer();
+
+ int count = 1;
+ while (Character.isJavaIdentifierPart((char) ch)) {
+ buf2.append((char) ch);
+ count++;
+ ch = in.read();
+ }
+
+ if (ch == ':') { // Ok, formal parameter
+ in.skip("Ljava/lang/Object".length());
+ buf.append(buf2);
+
+ ch = in.read();
+ in.unread();
+ // System.out.println("so far:" + buf2 + ":next:" +(char)ch);
+ } else {
+ for (int i = 0; i < count; i++)
+ in.unread();
+ }
+
+ return;
+ }
+
+ StringBuffer buf2 = new StringBuffer();
+ ch = in.read();
+
+ do {
+ buf2.append((char) ch);
+ ch = in.read();
+ // System.out.println("within ident:"+ (char)ch);
+
+ } while ((ch != -1) && (Character.isJavaIdentifierPart((char) ch) || (ch == '/')));
+
+ buf.append(buf2.toString().replace('/', '.'));
+
+ // System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
+
+ if (ch != -1)
+ in.unread();
+ }
+
+ private static final void matchGJIdent(MyByteArrayInputStream in, StringBuffer buf) {
+ int ch;
+
+ matchIdent(in, buf);
+
+ ch = in.read();
+ if ((ch == '<') || ch == '(') { // Parameterized or method
+ // System.out.println("Enter <");
+ buf.append((char) ch);
+ matchGJIdent(in, buf);
+
+ while (((ch = in.read()) != '>') && (ch != ')')) { // List of parameters
+ if (ch == -1)
+ throw new RuntimeException("Illegal signature: " + in.getData() + " reaching EOF");
+
+ // System.out.println("Still no >");
+ buf.append(", ");
+ in.unread();
+ matchGJIdent(in, buf); // Recursive call
+ }
+
+ // System.out.println("Exit >");
+
+ buf.append((char) ch);
+ } else
+ in.unread();
+
+ ch = in.read();
+ if (identStart(ch)) {
+ in.unread();
+ matchGJIdent(in, buf);
+ } else if (ch == ')') {
+ in.unread();
+ return;
+ } else if (ch != ';')
+ throw new RuntimeException("Illegal signature: " + in.getData() + " read " + (char) ch);
+ }
+
+ public static String translate(String s) {
+ // System.out.println("Sig:" + s);
+ StringBuffer buf = new StringBuffer();
+
+ matchGJIdent(new MyByteArrayInputStream(s), buf);
+
+ return buf.toString();
+ }
+
+ public static final boolean isFormalParameterList(String s) {
+ return s.startsWith("<") && (s.indexOf(':') > 0);
+ }
+
+ public static final boolean isActualParameterList(String s) {
+ return s.startsWith("L") && s.endsWith(">;");
+ }
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ String s = getSignature();
+
+ return "Signature(" + s + ")";
+ }
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy(ConstantPool constant_pool) {
+ return (Signature) clone();
+ }
+
}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005 Contributors
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Adrian Colyer initial implementation
- * ******************************************************************/
-
-package org.aspectj.apache.bcel.classfile.tests;
-
-
-import org.aspectj.apache.bcel.classfile.GenericSignatureParser;
-import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.apache.bcel.classfile.Method;
-import org.aspectj.apache.bcel.classfile.Signature;
-import org.aspectj.apache.bcel.classfile.Signature.ClassSignature;
-import org.aspectj.apache.bcel.classfile.Signature.ClassTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.FieldTypeSignature;
-import org.aspectj.apache.bcel.classfile.Signature.SimpleClassTypeSignature;
-import org.aspectj.apache.bcel.util.SyntheticRepository;
-
-import junit.framework.TestCase;
-
-public class GenericSignatureParserTest extends TestCase {
-
- GenericSignatureParser parser;
-
- public void testSimpleTokenize() {
- String [] tokens = parser.tokenize("Ljava/lang/String;");
- assertEquals(new String[] {"Ljava","/","lang","/","String",";"},tokens);
- }
-
- public void testTokenizeWithWildTypeArguments() {
- String[] tokens = parser.tokenize("Ljava/lang/String<*>;");
- assertEquals(new String[] {"Ljava","/","lang","/","String","<","*",">",";"},tokens);
- }
-
- public void testTokenizeWithExtendsTypeArguments() {
- String[] tokens = parser.tokenize("Ljava/util/List<+TE>;");
- assertEquals(new String[] {"Ljava","/","util","/","List","<","+","TE",">",";"},tokens);
- }
-
- public void testTokenizeWithSuperTypeArguments() {
- String[] tokens = parser.tokenize("Ljava/util/List<-TE>;");
- assertEquals(new String[] {"Ljava","/","util","/","List","<","-","TE",">",";"},tokens);
- }
-
- public void testTokenizeArrayType() {
- String [] tokens = parser.tokenize("[Ljava/lang/String;");
- assertEquals(new String[] {"[","Ljava","/","lang","/","String",";"},tokens);
- }
-
- public void testTokenizeFormalTypeParameters() {
- String[] tokens = parser.tokenize("<T:Ljava/lang/String;:Ljava/util/Comparable;>");
- assertEquals(new String[] {"<","T",":","Ljava","/","lang","/","String",";",":","Ljava","/","util","/","Comparable",";",">"},tokens);
- }
-
- public void testParseClassSignatureSimple() {
- ClassSignature sig = parser.parseAsClassSignature("Ljava/lang/String;");
- assertEquals("No type parameters",0,sig.formalTypeParameters.length);
- assertEquals("No superinterfaces",0,sig.superInterfaceSignatures.length);
- assertEquals("Ljava/lang/String;",sig.superclassSignature.classSignature);
- SimpleClassTypeSignature outerType = sig.superclassSignature.outerType;
- assertEquals("Ljava/lang/String;",outerType.identifier);
- assertEquals("No type args",0,outerType.typeArguments.length);
- }
-
- public void testParseClassSignatureTypeArgs() {
- ClassSignature sig = parser.parseAsClassSignature("Ljava/util/List<+Ljava/lang/String;>;");
- assertEquals("No type parameters",0,sig.formalTypeParameters.length);
- assertEquals("No superinterfaces",0,sig.superInterfaceSignatures.length);
- assertEquals("Ljava/util/List<+Ljava/lang/String;>;",sig.superclassSignature.classSignature);
- SimpleClassTypeSignature outerType = sig.superclassSignature.outerType;
- assertEquals("Ljava/util/List",outerType.identifier);
- assertEquals("One type arg",1,outerType.typeArguments.length);
- assertTrue(outerType.typeArguments[0].isPlus);
- assertEquals("+Ljava/lang/String;",outerType.typeArguments[0].toString());
- }
-
- public void testParseClassSignatureTheFullMonty() {
- ClassSignature sig = parser.parseAsClassSignature("<E:Ljava/lang/String;:Ljava/lang/Number<TE;>;>Ljava/util/List<TE;>;Ljava/util/Comparable<-TE;>;");
- assertEquals("1 formal parameter",1,sig.formalTypeParameters.length);
- assertEquals("E",sig.formalTypeParameters[0].identifier);
- ClassTypeSignature fsig = (ClassTypeSignature) sig.formalTypeParameters[0].classBound;
- assertEquals("Ljava/lang/String;",fsig.classSignature);
- assertEquals("1 interface bound",1,sig.formalTypeParameters[0].interfaceBounds.length);
- ClassTypeSignature isig = (ClassTypeSignature) sig.formalTypeParameters[0].interfaceBounds[0];
- assertEquals("Ljava/lang/Number<TE;>;",isig.classSignature);
- assertEquals("Ljava/util/List<TE;>;",sig.superclassSignature.classSignature);
- assertEquals("1 type argument",1,sig.superclassSignature.outerType.typeArguments.length);
- assertEquals("TE;",sig.superclassSignature.outerType.typeArguments[0].toString());
- assertEquals("1 super interface",1,sig.superInterfaceSignatures.length);
- assertEquals("Ljava/util/Comparable<-TE;>;",sig.superInterfaceSignatures[0].toString());
- }
-
- public void testClassSignatureParsingInJDK() throws Exception {
- SyntheticRepository repository = SyntheticRepository.getInstance();
- String[] testClasses = new String[] {
- "java.lang.Comparable",
- "java.lang.Iterable",
- "java.lang.Class",
- "java.lang.Enum",
- "java.lang.InheritableThreadLocal",
- "java.lang.ThreadLocal",
- "java.util.Collection",
- "java.util.Comparator",
- "java.util.Enumeration",
- "java.util.Iterator",
- "java.util.List",
- "java.util.ListIterator",
- "java.util.Map",
- "java.util.Map$Entry",
- "java.util.Queue",
- "java.util.Set",
- "java.util.SortedMap",
- "java.util.SortedSet"
- };
- for (int i = 0; i < testClasses.length; i++) {
- JavaClass jc = repository.loadClass(testClasses[i]);
- String sig = jc.getGenericSignature();
- parser.parseAsClassSignature(sig);
- }
- }
-
- public void testFieldSignatureParsingClassType() {
- FieldTypeSignature fsig = parser.parseAsFieldSignature("Ljava/lang/String;");
- assertTrue("ClassTypeSignature", fsig instanceof ClassTypeSignature);
- assertEquals("Ljava/lang/String;",fsig.toString());
- }
-
- public void testFieldSignatureParsingArrayType() {
- FieldTypeSignature fsig = parser.parseAsFieldSignature("[Ljava/lang/String;");
- assertTrue("ArrayTypeSignature", fsig instanceof Signature.ArrayTypeSignature);
- assertEquals("[Ljava/lang/String;",fsig.toString());
- }
-
- public void testFieldSignatureParsingTypeVariable() {
- FieldTypeSignature fsig = parser.parseAsFieldSignature("TT;");
- assertTrue("TypeVariableSignature",fsig instanceof Signature.TypeVariableSignature);
- assertEquals("TT;",fsig.toString());
- }
-
- public void testSimpleMethodSignatureParsing() {
- Signature.MethodTypeSignature mSig = parser.parseAsMethodSignature("()V");
- assertEquals("No type parameters",0,mSig.formalTypeParameters.length);
- assertEquals("No parameters",0,mSig.parameters.length);
- assertEquals("Void return type","V",mSig.returnType.toString());
- assertEquals("No throws",0,mSig.throwsSignatures.length);
- }
-
- public void testMethodSignatureTypeParams() {
- Signature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>(TT;)V");
- assertEquals("One type parameter",1,mSig.formalTypeParameters.length);
- assertEquals("T",mSig.formalTypeParameters[0].identifier);
- assertEquals("Ljava/lang/Object;",mSig.formalTypeParameters[0].classBound.toString());
- assertEquals("One parameter",1,mSig.parameters.length);
- assertEquals("TT;",mSig.parameters[0].toString());
- assertEquals("Void return type","V",mSig.returnType.toString());
- assertEquals("No throws",0,mSig.throwsSignatures.length);
- }
-
- public void testMethodSignatureGenericReturn() {
- Signature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>()TT;");
- assertEquals("One type parameter",1,mSig.formalTypeParameters.length);
- assertEquals("T",mSig.formalTypeParameters[0].identifier);
- assertEquals("Ljava/lang/Object;",mSig.formalTypeParameters[0].classBound.toString());
- assertEquals("No parameters",0,mSig.parameters.length);
- assertEquals("'T' return type","TT;",mSig.returnType.toString());
- assertEquals("No throws",0,mSig.throwsSignatures.length);
- }
-
- public void testMethodSignatureThrows() {
- Signature.MethodTypeSignature mSig = parser.parseAsMethodSignature("<T:>(TT;)V^Ljava/lang/Exception;^Ljava/lang/RuntimeException;");
- assertEquals("One type parameter",1,mSig.formalTypeParameters.length);
- assertEquals("T",mSig.formalTypeParameters[0].identifier);
- assertEquals("Ljava/lang/Object;",mSig.formalTypeParameters[0].classBound.toString());
- assertEquals("One parameter",1,mSig.parameters.length);
- assertEquals("TT;",mSig.parameters[0].toString());
- assertEquals("Void return type","V",mSig.returnType.toString());
- assertEquals("2 throws",2,mSig.throwsSignatures.length);
- assertEquals("Ljava/lang/Exception;",mSig.throwsSignatures[0].toString());
- assertEquals("Ljava/lang/RuntimeException;",mSig.throwsSignatures[1].toString());
- }
-
- public void testMethodSignaturePrimitiveParams() {
- Signature.MethodTypeSignature mSig = parser.parseAsMethodSignature("(ILjava/lang/Object;)V");
- assertEquals("2 parameters",2,mSig.parameters.length);
- assertEquals("I",mSig.parameters[0].toString());
- assertEquals("Ljava/lang/Object;",mSig.parameters[1].toString());
- }
-
- public void testMethodSignatureParsingInJDK() throws Exception{
- SyntheticRepository repository = SyntheticRepository.getInstance();
- String[] testClasses = new String[] {
- "java.lang.Comparable",
- "java.lang.Iterable",
- "java.lang.Class",
- "java.lang.Enum",
- "java.lang.InheritableThreadLocal",
- "java.lang.ThreadLocal",
- "java.util.Collection",
- "java.util.Comparator",
- "java.util.Enumeration",
- "java.util.Iterator",
- "java.util.List",
- "java.util.ListIterator",
- "java.util.Map",
- "java.util.Map$Entry",
- "java.util.Queue",
- "java.util.Set",
- "java.util.SortedMap",
- "java.util.SortedSet"
- };
- for (int i = 0; i < testClasses.length; i++) {
- JavaClass jc = repository.loadClass(testClasses[i]);
- Method[] methods = jc.getMethods();
- for (int j = 0; j < methods.length; j++) {
- String sig = methods[j].getGenericSignature();
- if (sig != null) parser.parseAsMethodSignature(sig);
- }
- }
- }
-
- public void testFullyQualifiedSuperclassAfterTypeParams() {
- try {
- Signature.FieldTypeSignature cSig = parser.parseAsFieldSignature("Ljava/util/List</;");
- fail("Expected IllegalStateException");
- } catch (IllegalStateException ex) {
- assertTrue(ex.getMessage().indexOf("Ljava/util/List</;") != -1);
- }
- }
-
- public void testPr107784() {
- parser.parseAsMethodSignature(
- "(Lcom/cibc/responders/mapping/CommonDataBeanScenario;Ljava/lang/Object;)Lcom/cibc/responders/response/Formatter<[BLjava/lang/Object;>;");
- parser.parseAsClassSignature("<Parent:Ljava/lang/Object;Child:Ljava/lang/Object;>Ljava/lang/Object;");
- }
-
- private void assertEquals(String[] expected, String[] actual) {
- if (actual.length != expected.length) {
- int shorter = Math.min(expected.length,actual.length);
- for (int i = 0; i < shorter; i++) {
- if (!actual[i].equals(expected[i])) {
- fail("Expected " + expected[i] + " at position " + i + " but found " +
- actual[i]);
- }
- }
- fail("Expected " + expected.length + " tokens but got " + actual.length +
- tokensToString(actual));
- }
- for (int i = 0; i < actual.length; i++) {
- if (!actual[i].equals(expected[i])) {
- fail("Expected " + expected[i] + " at position " + i + " but found " +
- actual[i]);
- }
- }
- }
-
- private String tokensToString(String[] tokens) {
- StringBuffer sb = new StringBuffer();
- sb.append(tokens[0]);
- for (int i = 1; i < tokens.length; i++) {
- sb.append(",");
- sb.append(tokens[i]);
- }
- return sb.toString();
- }
-
- protected void setUp() throws Exception {
- super.setUp();
- parser = new GenericSignatureParser();
- }
-}