Browse Source

BCEL Java5 Support

tags/Root_AspectJ5_Development
aclement 19 years ago
parent
commit
8644e07c0d
42 changed files with 4863 additions and 8 deletions
  1. 6
    4
      bcel-builder/.classpath
  2. 9
    2
      bcel-builder/build.xml
  3. 0
    0
      bcel-builder/notamodule
  4. 60
    2
      bcel-builder/readme.html
  5. 125
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/Annotation.java
  6. 51
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationElementValue.java
  7. 66
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ArrayElementValue.java
  8. 53
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ClassElementValue.java
  9. 62
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePair.java
  10. 112
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementValue.java
  11. 63
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/EnumElementValue.java
  12. 83
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeAnnotations.java
  13. 40
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisibleAnnotations.java
  14. 34
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisibleParameterAnnotations.java
  15. 110
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeParameterAnnotations.java
  16. 40
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisibleAnnotations.java
  17. 34
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisibleParameterAnnotations.java
  18. 119
    0
      bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValue.java
  19. 55
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/AnnotationElementValueGen.java
  20. 148
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/AnnotationGen.java
  21. 87
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ArrayElementValueGen.java
  22. 59
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ClassElementValueGen.java
  23. 70
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ElementNameValuePairGen.java
  24. 137
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ElementValueGen.java
  25. 84
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/EnumElementValueGen.java
  26. 173
    0
      bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/SimpleElementValueGen.java
  27. 54
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AllTests.java
  28. 55
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AnnotationAccessFlagTest.java
  29. 49
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AnnotationDefaultAttributeTest.java
  30. 122
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AnnotationGenTest.java
  31. 150
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java
  32. 227
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ElementValueGenTest.java
  33. 104
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java
  34. 56
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnumAccessFlagTest.java
  35. 147
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/FieldAnnotationsTest.java
  36. 633
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/GeneratingAnnotatedClassesTest.java
  37. 72
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/LocalVariableTypeTableTest.java
  38. 108
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/MethodAnnotationsTest.java
  39. 593
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ParameterAnnotationsTest.java
  40. 373
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/RuntimeVisibleAnnotationAttributeTest.java
  41. 143
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/RuntimeVisibleParameterAnnotationAttributeTest.java
  42. 97
    0
      bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/VarargsTest.java

+ 6
- 4
bcel-builder/.classpath View File

@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/lib/regexp/jakarta-regexp-1.2.jar"/>
<classpathentry kind="output" path="bin"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="testsrc"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/lib/regexp/jakarta-regexp-1.2.jar"/>
<classpathentry sourcepath="/lib/junit/junit-src.jar" kind="lib" path="/lib/junit/junit.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

+ 9
- 2
bcel-builder/build.xml View File

@@ -1,10 +1,12 @@
<project default="extractAndPatchAndJar" basedir=".">
<project default="packageAndPush" basedir=".">

<!-- top-level -->
<target name="extractAndPatchAndJar" depends="extractAndPatch,jar,srcjar" />

<target name="extractAndPatch" depends="unzipSource,createPatchedSource" />

<target name="packageAndPush" depends="buildTheJars,push"/>
<target name="jar" depends="pack">
<copy file="../lib/regexp/jakarta-regexp-1.2.jar"
tofile="bcel/lib/Regex.jar" />
@@ -20,6 +22,11 @@
<copy file="bcel.jar" todir="../lib/bcel" />
<copy file="bcel-src.zip" todir="../lib/bcel" />
</target>
<target name="buildTheJars">
<zip file="bcel.jar" basedir="bin" includes="**/*" excludes="**/tests/*.class"/>
<zip file="bcel-src.zip" basedir="src" includes="**/*"/>
</target>
<target name="diff" depends="transformFromAJ,pack">

+ 0
- 0
bcel-builder/notamodule View File


+ 60
- 2
bcel-builder/readme.html View File

@@ -6,15 +6,73 @@
<body>
<h1>The BCEL-builder module</h1>

This module includes a modified form of BCEL - with some fixes in *and* support for Java5.

<hr>

<h3>Java 5 support</h3>
<p>The best way to see how it works is look in the testcases. The only feature that
is definetly not implemented yet is package level annotations. What is working is:</p>
<ul>
<li>You can ask a type: are you an annotation type? are you an enum type?</li>
<li>You can ask a method: were you defined with varargs? Are you a bridge method?</li>
<li>All annotation values types are supported (primitive, string, array, enum, annotation, class).</li>
<li>Runtime visible and invisible annotations are supported.</li>
<li>Annotations are accessible on types, methods, fields.</li>
<li>Parameter annotations are accessible on methods.</li>
<li>You can programmatically construct annotations and attach them to types, methods, fields.</li>
<li>You can construct parameter annotations and add them to methods.</li>
<li>The EnclosingMethod attribute is supported (it is used to let you know the containing method for local/anonymous types)</li>
<li>The LocalVariableTypeTable attribute is supported (used for generics to tell you the original variable signature)</li>
</ul>
<p>All this is implemented without using any Java 5 APIs.</p>
<p>There are a number of new TODO type tags in the code that may prove useful:</p>
<ul>
<li>J5SUPPORT: Marks places where BCEL has been changed for 1.5 (might have missed a couple...)</li>
<li>BCELBUG: Marks things that might be BCEL problems that I came across</li>
<li>J5TODO: Marks either a missing bit of implementation (hopefully corner case) or an optimization we could make</li>
</ul>
<hr>
<p> The contents of this directory are:
</p>

<ul>
<li>This file</li>
<li>build.xml -- an ant script </li>
<li>patch.txt -- a diff patchfile</li>
<li>src -- contains the source for BCEL, a modified variant of BCEL 5.1 that includes bug fixes and Java 5 support</li>
<li>testsrc -- JUnit test cases for the Java 5 support</li>
<li>testdata -- Java5 testcode that can be built using the build.xml script in the testdata directory (see note on this below)</li>
<li>build.xml -- an ant script for manipulating the src folder, possibly useful if ever merging a base BCEL version</li>
</ul>

<hr>
<h3>Development Process</h3>
<p>
We can now follow normal TDD for this. Add a JUnit testcase to the testsrc folder, plus any
associated test materials into the testdata directory. Then change BCEL to get your test passing,
when you are happy with the result (i.e. all the tests in the bcel-builder module are passing), you
should execute the build.xml script whose default target will package up bcel (and bcel src) and
deliver it into the lib module, the rest of AspectJ is driven off the version of bcel in the lib/bcel
folder - it is *not* driven off the bcel-builder code (we could choose to change that sometime later).
<p>
Once you have done this execute all the tests for AspectJ, if they all pass you can check in your
mods for bcel-builder and to the lib project.

<hr>
<h3>testdata</h3>
The testdata folder includes a load of Java5 code, it needs to be built with a Java5 compiler. There
is an ant script in there (build.xml) that builds all the source code into a testcode.jar which is
then used by the testcases - so if you do change the testdata code then you should run build.xml
to rebuild testcode.jar.

<hr>
<h3>The old stuff...</h3>
Before the Java 5 support was added we maintained this module as basically a patch to apply against
a particular download of BCEL. Changes to BCEL are occurring more frequently than we integrate
a new version of BCEL so it made sense to make the patching process easier, so we have checked in
the modified source for BCEL.
The original instructions for patching BCEL in the old way are below...

<p> And pretty much nothing else. Well, then, what do you do with
this directory? Well, the whole point is to generate bcel/bcel.jar in
the lib package. To do so, first stick

+ 125
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/Annotation.java View File

@@ -0,0 +1,125 @@
/* *******************************************************************
* Copyright (c) 2004 IBM Corporation
*
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement initial implementation
* ******************************************************************/
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.Utility;

/**
* An annotation is an immutable object (AnnotationGen is the mutable variant) - it basically contains a list
* of name-value pairs.
*/
public class Annotation {
private int typeIndex;
private List /* ElementNameValuePair */ evs;
private ConstantPool cpool;
private boolean isRuntimeVisible;
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("ANNOTATION ["+getTypeSignature()+"] ["+
(isRuntimeVisible?"runtimeVisible":"runtimeInvisible")+"] [");
for (Iterator iter = evs.iterator(); iter.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) iter.next();
sb.append(element.toString());
if (iter.hasNext()) sb.append(",");
}
sb.append("]");
return sb.toString();
}
private Annotation(ConstantPool cpool) {
this.cpool = cpool;
}
protected static Annotation read(DataInputStream dis,ConstantPool cpool,boolean isRuntimeVisible) throws IOException {
Annotation a = new Annotation(cpool);
a.typeIndex = dis.readUnsignedShort();
int elemValuePairCount = dis.readUnsignedShort();
for (int i=0;i<elemValuePairCount;i++) {
int nidx = dis.readUnsignedShort();
a.addElementNameValuePair(
new ElementNameValuePair(nidx,ElementValue.readElementValue(dis,cpool),cpool));
}
a.isRuntimeVisible(isRuntimeVisible);
return a;
}
protected void dump(DataOutputStream dos) throws IOException {
dos.writeShort(typeIndex); // u2 index of type name in cpool
dos.writeShort(evs.size()); // u2 element_value pair count
for (int i = 0 ; i<evs.size();i++) {
ElementNameValuePair envp = (ElementNameValuePair) evs.get(i);
envp.dump(dos);
}
}
public void addElementNameValuePair(ElementNameValuePair evp) {
if (evs == null) evs = new ArrayList();
evs.add(evp);
}
public int getTypeIndex() {
return typeIndex;
}
public final String getTypeSignature() {
ConstantUtf8 c = (ConstantUtf8)cpool.getConstant(typeIndex,Constants.CONSTANT_Utf8);
return c.getBytes();
}
public final String getTypeName() {
ConstantUtf8 c = (ConstantUtf8)cpool.getConstant(typeIndex,Constants.CONSTANT_Utf8);
return Utility.signatureToString(c.getBytes());
}
/**
* Returns list of ElementNameValuePair objects
*/
public List getValues() {
return evs;
}

protected void isRuntimeVisible(boolean b) {
isRuntimeVisible = b;
}
public boolean isRuntimeVisible() {
return isRuntimeVisible;
}

public String toShortString() {
StringBuffer result = new StringBuffer();
result.append("@");
result.append(getTypeName());
if (getValues().size()>0) {
result.append("(");
for (Iterator iter = getValues().iterator(); iter.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) iter.next();
result.append(element.toShortString());
}
result.append(")");
}
return result.toString();
}
}

+ 51
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationElementValue.java View File

@@ -0,0 +1,51 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.ConstantPool;

/**
* An element value that is an annotation.
*/
public class AnnotationElementValue extends ElementValue {
// For annotation element values, this is the annotation
private Annotation a;
public AnnotationElementValue(int type, Annotation annotation, ConstantPool cpool) {
super(type,cpool);
if (type != ANNOTATION)
throw new RuntimeException("Only element values of type annotation can be built with this ctor");
this.a = annotation;
}

public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 type of value (ANNOTATION == '@')
a.dump(dos);
}
public String stringifyValue() {
StringBuffer sb = new StringBuffer();
sb.append(a.toString());
return sb.toString();
}
public String toString() {
return stringifyValue();
}
public Annotation getAnnotation() { return a;}
}

+ 66
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ArrayElementValue.java View File

@@ -0,0 +1,66 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.ConstantPool;


public class ArrayElementValue extends ElementValue {
// For array types, this is the array
private ElementValue[] evalues;
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("{");
for (int i = 0; i < evalues.length; i++) {
sb.append(evalues[i].toString());
if ((i+1)<evalues.length) sb.append(",");
}
sb.append("}");
return sb.toString();
}
public ArrayElementValue(int type, ElementValue[] datums, ConstantPool cpool) {
super(type,cpool);
if (type != ARRAY)
throw new RuntimeException("Only element values of type array can be built with this ctor");
this.evalues = datums;
}

public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 type of value (ARRAY == '[')
dos.writeShort(evalues.length);
for (int i=0; i<evalues.length; i++) {
evalues[i].dump(dos);
}
}
public String stringifyValue() {
StringBuffer sb = new StringBuffer();
sb.append("[");
for(int i=0; i<evalues.length; i++) {
sb.append(evalues[i].stringifyValue());
if ((i+1)<evalues.length) sb.append(",");
}
sb.append("]");
return sb.toString();
}
public ElementValue[] getElementValuesArray() { return evalues;}
public int getElementValuesArraySize() { return evalues.length;}
}

+ 53
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ClassElementValue.java View File

@@ -0,0 +1,53 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;


public class ClassElementValue extends ElementValue {
// For primitive types and string type, this points to the value entry in the cpool
// For 'class' this points to the class entry in the cpool
private int idx;
protected ClassElementValue(int type,int idx,ConstantPool cpool) {
super(type,cpool);
this.idx = idx;
}
public int getIndex() {
return idx;
}
public String getClassString() {
ConstantUtf8 c = (ConstantUtf8)cpool.getConstant(idx,Constants.CONSTANT_Utf8);
return c.getBytes();
}
public String stringifyValue() {
ConstantUtf8 cu8 = (ConstantUtf8)cpool.getConstant(idx,Constants.CONSTANT_Utf8);
return cu8.getBytes();
}
public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 kind of value
dos.writeShort(idx);
}
}

+ 62
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementNameValuePair.java View File

@@ -0,0 +1,62 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;


public class ElementNameValuePair {
private int nameIdx;
private ElementValue value;
private ConstantPool cpool;

public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getNameString()+"="+value.toString());
return sb.toString();
}
public ElementNameValuePair(int idx,ElementValue value,ConstantPool cpool) {
this.nameIdx = idx;
this.value = value;
this.cpool = cpool;
}
protected void dump(DataOutputStream dos) throws IOException {
dos.writeShort(nameIdx); // u2 name of the element
value.dump(dos);
}
public int getNameIndex() {
return nameIdx;
}
public final String getNameString() {
ConstantUtf8 c = (ConstantUtf8)cpool.getConstant(nameIdx,Constants.CONSTANT_Utf8);
return c.getBytes();
}
public final ElementValue getValue() {
return value;
}

public String toShortString() {
StringBuffer result = new StringBuffer();
result.append(getNameString()).append("=").append(getValue().toShortString());
return result.toString();
}
}

+ 112
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementValue.java View File

@@ -0,0 +1,112 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.aspectj.apache.bcel.classfile.ConstantPool;

public abstract class ElementValue {

protected int type;
protected ConstantPool cpool;
public String toString() {
return stringifyValue();
}

protected ElementValue(int type,ConstantPool cpool) {
this.type = type;
this.cpool = cpool;
}
public int getElementValueType() {
return type;
}
public abstract String stringifyValue();
public abstract void dump(DataOutputStream dos) throws IOException;

public static final int STRING = 's';
public static final int ENUM_CONSTANT = 'e';
public static final int CLASS = 'c';
public static final int ANNOTATION = '@';
public static final int ARRAY = '[';
public static final int PRIMITIVE_INT = 'I';
public static final int PRIMITIVE_BYTE = 'B';
public static final int PRIMITIVE_CHAR = 'C';
public static final int PRIMITIVE_DOUBLE = 'D';
public static final int PRIMITIVE_FLOAT = 'F';
public static final int PRIMITIVE_LONG = 'J';
public static final int PRIMITIVE_SHORT = 'S';
public static final int PRIMITIVE_BOOLEAN= 'Z';
public static ElementValue readElementValue(DataInputStream dis,ConstantPool cpool) throws IOException {
int type= dis.readUnsignedByte();
switch (type) {
case 'B': // byte
return new SimpleElementValue(PRIMITIVE_BYTE,dis.readUnsignedShort(),cpool);
case 'C': // char
return new SimpleElementValue(PRIMITIVE_CHAR,dis.readUnsignedShort(),cpool);
case 'D': // double
return new SimpleElementValue(PRIMITIVE_DOUBLE,dis.readUnsignedShort(),cpool);
case 'F': // float
return new SimpleElementValue(PRIMITIVE_FLOAT,dis.readUnsignedShort(),cpool);
case 'I': // int
return new SimpleElementValue(PRIMITIVE_INT,dis.readUnsignedShort(),cpool);
case 'J': // long
return new SimpleElementValue(PRIMITIVE_LONG,dis.readUnsignedShort(),cpool);
case 'S': // short
return new SimpleElementValue(PRIMITIVE_SHORT,dis.readUnsignedShort(),cpool);
case 'Z': // boolean
return new SimpleElementValue(PRIMITIVE_BOOLEAN,dis.readUnsignedShort(),cpool);
case 's': // String
return new SimpleElementValue(STRING,dis.readUnsignedShort(),cpool);

case 'e': // Enum constant
return new EnumElementValue(ENUM_CONSTANT,dis.readUnsignedShort(),dis.readUnsignedShort(),cpool);

case 'c': // Class
return new ClassElementValue(CLASS,dis.readUnsignedShort(),cpool);

//J5TODO: Should it be 'true' in the next statement? What difference does it make? Should it be
// the same as the 'super annotation' in which we are contained?
case '@': // Annotation
return new AnnotationElementValue(ANNOTATION,Annotation.read(dis,cpool,true),cpool);
case '[': // Array
int numArrayVals = dis.readUnsignedShort();
List arrayVals = new ArrayList();
ElementValue[] evalues = new ElementValue[numArrayVals];
for (int j=0;j<numArrayVals;j++) {
evalues[j] = ElementValue.readElementValue(dis,cpool);
}
return new ArrayElementValue(ARRAY,evalues,cpool);

default:
throw new RuntimeException("Unexpected element value kind in annotation: "+type);
}
}


public String toShortString() {
StringBuffer result = new StringBuffer();
result.append(stringifyValue());
return result.toString();
}
}

+ 63
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/EnumElementValue.java View File

@@ -0,0 +1,63 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.Utility;


public class EnumElementValue extends ElementValue {
// For enum types, these two indices point to the type and value
private int typeIdx;
private int valueIdx;
public EnumElementValue(int type,int typeIdx,int valueIdx,ConstantPool cpool) {
super(type,cpool);
if (type != ENUM_CONSTANT)
throw new RuntimeException("Only element values of type enum can be built with this ctor");
this.typeIdx = typeIdx;
this.valueIdx= valueIdx;
}
public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e')
dos.writeShort(typeIdx); // u2
dos.writeShort(valueIdx); // u2
}
public String stringifyValue() {
ConstantUtf8 cu8 = (ConstantUtf8)cpool.getConstant(valueIdx,Constants.CONSTANT_Utf8);
return cu8.getBytes();
}
public String getEnumTypeString() {
ConstantUtf8 cu8 = (ConstantUtf8)cpool.getConstant(typeIdx,Constants.CONSTANT_Utf8);
return Utility.signatureToString(cu8.getBytes());
}
public String getEnumValueString() {
ConstantUtf8 cu8 = (ConstantUtf8)cpool.getConstant(valueIdx,Constants.CONSTANT_Utf8);
return cu8.getBytes();
}
public int getValueIndex() { return valueIdx;}
public int getTypeIndex() { return typeIdx; }

}

+ 83
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeAnnotations.java View File

@@ -0,0 +1,83 @@
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;

public abstract class RuntimeAnnotations extends Attribute {

private List /*Annotation*/ annotations;
private boolean visible;
// Keep just a byte stream of the data until someone actually asks for it
private boolean inflated = false;
private byte[] annotation_data;
public RuntimeAnnotations(byte attrid, boolean visible,
int nameIdx, int len,
ConstantPool cpool) {
super(attrid,nameIdx,len,cpool);
this.visible = visible;
annotations = new ArrayList();
}
public RuntimeAnnotations(byte attrid,boolean visible,int nameIdx,int len,byte[] data,ConstantPool cpool) {
super(attrid,nameIdx,len,cpool);
this.visible = visible;
annotations = new ArrayList();
annotation_data = data;
}
public List getAnnotations() {
if (!inflated) inflate();
return annotations;
}
public boolean areVisible() {
return visible;
}

protected void readAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException {
annotation_data = new byte[length];
dis.read(annotation_data,0,length);
}

private void inflate() {
try {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data));
int numberOfAnnotations = dis.readUnsignedShort();
for (int i = 0 ;i<numberOfAnnotations;i++) {
annotations.add(Annotation.read(dis,getConstantPool(),visible));
}
dis.close();
inflated = true;
} catch (IOException ioe) {
throw new RuntimeException("Unabled to inflate annotation data, badly formed? ");
}
}
protected void writeAnnotations(DataOutputStream dos) throws IOException {
if (!inflated) {
dos.write(annotation_data,0,length);
} else {
dos.writeShort(annotations.size());
for (Iterator i = annotations.iterator(); i.hasNext();) {
Annotation ann = (Annotation) i.next();
ann.dump(dos);
}
}
}
/** FOR TESTING ONLY: Tells you if the annotations have been inflated to an object graph */
public boolean isInflated() {
return inflated;
}
}

+ 40
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisibleAnnotations.java View File

@@ -0,0 +1,40 @@
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.Visitor;

public class RuntimeInvisibleAnnotations extends RuntimeAnnotations {
public RuntimeInvisibleAnnotations(int nameIdx, int len, ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, false, nameIdx, len, cpool);
}

public RuntimeInvisibleAnnotations(int nameIdx, int len,
DataInputStream dis,ConstantPool cpool) throws IOException {
this(nameIdx, len, cpool);
readAnnotations(dis,cpool);
}
public RuntimeInvisibleAnnotations(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS,true,nameIndex,len,rvaData,cpool);
}

public void accept(Visitor v) {
v.visitRuntimeInvisibleAnnotations(this);
}

public final void dump(DataOutputStream dos) throws IOException {
super.dump(dos);
writeAnnotations(dos);
}

public Attribute copy(ConstantPool constant_pool) {
throw new RuntimeException("Not implemented yet!");
}
}

+ 34
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisibleParameterAnnotations.java View File

@@ -0,0 +1,34 @@
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataInputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.Visitor;

public class RuntimeInvisibleParameterAnnotations extends RuntimeParameterAnnotations {
public RuntimeInvisibleParameterAnnotations(int nameIdx, int len, ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, false, nameIdx, len, cpool);
}

public RuntimeInvisibleParameterAnnotations(int nameIdx, int len,
DataInputStream dis,ConstantPool cpool) throws IOException {
this(nameIdx, len, cpool);
readParameterAnnotations(dis,cpool);
}
public RuntimeInvisibleParameterAnnotations(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,true,nameIndex,len,rvaData,cpool);
}

public void accept(Visitor v) {
v.visitRuntimeInvisibleParameterAnnotations(this);
}

public Attribute copy(ConstantPool constant_pool) {
throw new RuntimeException("Not implemented yet!");
}
}

+ 110
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeParameterAnnotations.java View File

@@ -0,0 +1,110 @@
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;

public abstract class RuntimeParameterAnnotations extends Attribute {
private List /*Annotation[]*/ parameterAnnotations;
private boolean visible;

// Keep just a byte stream of the data until someone actually asks for it
private boolean inflated = false;
private byte[] annotation_data;

public RuntimeParameterAnnotations(byte attrid, boolean visible,
int nameIdx, int len, ConstantPool cpool) {
super(attrid,nameIdx,len,cpool);
this.visible = visible;
parameterAnnotations = new ArrayList();
}
public RuntimeParameterAnnotations(byte attrid,boolean visible,int nameIdx,int len,byte[] data,ConstantPool cpool) {
super(attrid,nameIdx,len,cpool);
this.visible = visible;
parameterAnnotations = new ArrayList();
annotation_data = data;
}
public final void dump(DataOutputStream dos) throws IOException {
super.dump(dos);
writeAnnotations(dos);
}

public Attribute copy(ConstantPool constant_pool) {
throw new RuntimeException("Not implemented yet!");
}
/** Return a list of Annotation[] - each list entry contains the annotations for one parameter */
public List /*Annotation[]*/ getParameterAnnotations() {
if (!inflated) inflate();
return parameterAnnotations;
}
public Annotation[] getAnnotationsOnParameter(int parameterIndex) {
if (!inflated) inflate();
return (Annotation[])parameterAnnotations.get(parameterIndex);
}
public boolean areVisible() {
return visible;
}

protected void readParameterAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException {
annotation_data = new byte[length];
dis.read(annotation_data,0,length);
}

private void inflate() {
try {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data));
int numParameters = dis.readUnsignedByte();
for (int i=0; i<numParameters; i++) {
int numAnnotations = dis.readUnsignedShort();
Annotation[] annotations = new Annotation[numAnnotations];
for (int j=0; j<numAnnotations; j++) {
annotations[j] = Annotation.read(dis,getConstantPool(),visible);
}
parameterAnnotations.add(annotations);
}
inflated = true;
} catch (IOException ioe) {
throw new RuntimeException("Unabled to inflate annotation data, badly formed?");
}
}

protected void writeAnnotations(DataOutputStream dos) throws IOException {
if (!inflated) {
dos.write(annotation_data,0,length);
} else {
dos.writeByte(parameterAnnotations.size());
for (int i=0; i<parameterAnnotations.size(); i++) {
Annotation[] annotations = (Annotation[])parameterAnnotations.get(i);
dos.writeShort(annotations.length);
for (int j=0; j<annotations.length;j++) {
annotations[j].dump(dos);
}
}
}
}
/** FOR TESTING ONLY: Tells you if the annotations have been inflated to an object graph */
public boolean isInflated() {
return inflated;
}

public String toString() {
return "Runtime"+(visible?"Visible":"Invisible")+"ParameterAnnotations ["+(inflated?"inflated":"not yet inflated")+"]";
}

}

+ 40
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisibleAnnotations.java View File

@@ -0,0 +1,40 @@
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.Visitor;

public class RuntimeVisibleAnnotations extends RuntimeAnnotations {
public RuntimeVisibleAnnotations(int nameIdx, int len, ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, true, nameIdx, len, cpool);
}

public RuntimeVisibleAnnotations(int nameIdx, int len,
DataInputStream dis,ConstantPool cpool) throws IOException {
this(nameIdx, len, cpool);
readAnnotations(dis,cpool);
}

public RuntimeVisibleAnnotations(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS,true,nameIndex,len,rvaData,cpool);
}

public void accept(Visitor v) {
v.visitRuntimeVisibleAnnotations(this);
}

public final void dump(DataOutputStream dos) throws IOException {
super.dump(dos);
writeAnnotations(dos);
}

public Attribute copy(ConstantPool constant_pool) {
throw new RuntimeException("Not implemented yet!");
}
}

+ 34
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisibleParameterAnnotations.java View File

@@ -0,0 +1,34 @@
package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataInputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.Visitor;

public class RuntimeVisibleParameterAnnotations extends RuntimeParameterAnnotations {
public RuntimeVisibleParameterAnnotations(int nameIdx, int len, ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, true, nameIdx, len, cpool);
}
public RuntimeVisibleParameterAnnotations(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) {
super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,true,nameIndex,len,rvaData,cpool);
}

public RuntimeVisibleParameterAnnotations(int nameIdx, int len,
DataInputStream dis,ConstantPool cpool) throws IOException {
this(nameIdx, len, cpool);
readParameterAnnotations(dis,cpool);
}

public void accept(Visitor v) {
v.visitRuntimeVisibleParameterAnnotations(this);
}

public Attribute copy(ConstantPool constant_pool) {
throw new RuntimeException("Not implemented yet!");
}
}

+ 119
- 0
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValue.java View File

@@ -0,0 +1,119 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.ConstantDouble;
import org.aspectj.apache.bcel.classfile.ConstantFloat;
import org.aspectj.apache.bcel.classfile.ConstantInteger;
import org.aspectj.apache.bcel.classfile.ConstantLong;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;

/**
* An element value representing a primitive or string value.
*/
public class SimpleElementValue extends ElementValue {
// For primitive types and string type, this points to the value entry in the cpool
// For 'class' this points to the class entry in the cpool
private int idx;
protected SimpleElementValue(int type,int idx,ConstantPool cpool) {
super(type,cpool);
this.idx = idx;
}
public int getIndex() {
return idx;
}
public String getValueString() {
if (type != STRING)
throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue");
ConstantUtf8 c = (ConstantUtf8)cpool.getConstant(idx,Constants.CONSTANT_Utf8);
return c.getBytes();
}
public int getValueInt() {
if (type != PRIMITIVE_INT)
throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue");
ConstantInteger c = (ConstantInteger)cpool.getConstant(idx,Constants.CONSTANT_Integer);
return c.getBytes();
}
public String toString() {
return stringifyValue();
}
// Whatever kind of value it is, return it as a string
public String stringifyValue() {
switch (type) {
case PRIMITIVE_INT:
ConstantInteger c = (ConstantInteger)cpool.getConstant(idx,Constants.CONSTANT_Integer);
return Integer.toString(c.getBytes());
case PRIMITIVE_LONG:
ConstantLong j = (ConstantLong)cpool.getConstant(idx,Constants.CONSTANT_Long);
return Long.toString(j.getBytes());
case PRIMITIVE_DOUBLE:
ConstantDouble d = (ConstantDouble)cpool.getConstant(idx,Constants.CONSTANT_Double);
return Double.toString(d.getBytes());
case PRIMITIVE_FLOAT:
ConstantFloat f = (ConstantFloat)cpool.getConstant(idx,Constants.CONSTANT_Float);
return Float.toString(f.getBytes());
case PRIMITIVE_SHORT:
ConstantInteger s = (ConstantInteger)cpool.getConstant(idx,Constants.CONSTANT_Integer);
return Integer.toString(s.getBytes());
case PRIMITIVE_BYTE:
ConstantInteger b = (ConstantInteger)cpool.getConstant(idx,Constants.CONSTANT_Integer);
return Integer.toString(b.getBytes());
case PRIMITIVE_CHAR:
ConstantInteger ch = (ConstantInteger)cpool.getConstant(idx,Constants.CONSTANT_Integer);
return Integer.toString(ch.getBytes());
case PRIMITIVE_BOOLEAN:
ConstantInteger bo = (ConstantInteger)cpool.getConstant(idx,Constants.CONSTANT_Integer);
if (bo.getBytes() == 0) return "false";
if (bo.getBytes() != 0) return "true";
case STRING:
ConstantUtf8 cu8 = (ConstantUtf8)cpool.getConstant(idx,Constants.CONSTANT_Utf8);
return cu8.getBytes();
default:
throw new RuntimeException("SimpleElementValue class does not know how to stringify type "+type);
}
}
public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 kind of value
switch (type) {
case PRIMITIVE_INT:
case PRIMITIVE_BYTE:
case PRIMITIVE_CHAR:
case PRIMITIVE_FLOAT:
case PRIMITIVE_LONG:
case PRIMITIVE_BOOLEAN:
case PRIMITIVE_SHORT:
case PRIMITIVE_DOUBLE:
case STRING:
dos.writeShort(idx);
break;
default:
throw new RuntimeException("SimpleElementValue doesnt know how to write out type "+type);
}
}
}

+ 55
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/AnnotationElementValueGen.java View File

@@ -0,0 +1,55 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValue;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;


public class AnnotationElementValueGen extends ElementValueGen {
// For annotation element values, this is the annotation
private AnnotationGen a;
public AnnotationElementValueGen(AnnotationGen a,ConstantPoolGen cpool) {
super(ANNOTATION,cpool);
this.a = a;
}
public AnnotationElementValueGen(int type, AnnotationGen annotation, ConstantPoolGen cpool) {
super(type,cpool);
if (type != ANNOTATION)
throw new RuntimeException("Only element values of type annotation can be built with this ctor");
this.a = annotation;
}

public AnnotationElementValueGen(AnnotationElementValue value, ConstantPoolGen cpool) {
super(ANNOTATION,cpool);
a = new AnnotationGen(value.getAnnotation(),cpool);
}

public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 type of value (ANNOTATION == '@')
a.dump(dos);
}
public String stringifyValue() {
throw new RuntimeException("Not implemented yet");
}
public AnnotationGen getAnnotation() { return a;}
}

+ 148
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/AnnotationGen.java View File

@@ -0,0 +1,148 @@
/* *******************************************************************
* Copyright (c) 2004 IBM Corporation
*
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement initial implementation
* ******************************************************************/
package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.ObjectType;

public class AnnotationGen {
private int typeIndex;
private List /* ElementNameValuePairGen */ evs;
private ConstantPoolGen cpool;
private boolean isRuntimeVisible = false;
/**
* Here we are taking a fixed annotation of type Annotation and building a
* modifiable AnnotationGen object. The ConstantPool entries should already
* be correct, we could assert that ...
* We need to copy the type and the element name value pairs and the visibility.
*/
public AnnotationGen(Annotation a,ConstantPoolGen cpool) {
this.cpool = cpool;
// Could assert a.getTypeSignature() == (ConstantUtf8)cpool.getConstant(a.getTypeIndex())).getBytes()
typeIndex = a.getTypeIndex();
isRuntimeVisible = a.isRuntimeVisible();
evs = copyValues(a.getValues(),cpool);
}
private List copyValues(List in,ConstantPoolGen cpool) {
List out = new ArrayList();
for (Iterator iter = in.iterator(); iter.hasNext();) {
ElementNameValuePair nvp = (ElementNameValuePair) iter.next();
out.add(new ElementNameValuePairGen(nvp,cpool));
}
return out;
}
private AnnotationGen(ConstantPoolGen cpool) {
this.cpool = cpool;
}
public AnnotationGen(ObjectType type,List /*ElementNameValuePairGen*/ elements,boolean vis,ConstantPoolGen cpool) {
this.cpool = cpool;
this.typeIndex = cpool.addUtf8(type.getSignature());
evs = elements;
isRuntimeVisible = vis;
}
public static AnnotationGen read(DataInputStream dis,ConstantPoolGen cpool,boolean b) throws IOException {
AnnotationGen a = new AnnotationGen(cpool);
a.typeIndex = dis.readUnsignedShort();
int elemValuePairCount = dis.readUnsignedShort();
for (int i=0;i<elemValuePairCount;i++) {
int nidx = dis.readUnsignedShort();
a.addElementNameValuePair(
new ElementNameValuePairGen(nidx,ElementValueGen.readElementValue(dis,cpool),cpool));
}
a.isRuntimeVisible(b);
return a;
}
public void dump(DataOutputStream dos) throws IOException {
dos.writeShort(typeIndex); // u2 index of type name in cpool
dos.writeShort(evs.size()); // u2 element_value pair count
for (int i = 0 ; i<evs.size();i++) {
ElementNameValuePairGen envp = (ElementNameValuePairGen) evs.get(i);
envp.dump(dos);
}
}
public void addElementNameValuePair(ElementNameValuePairGen evp) {
if (evs == null) evs = new ArrayList();
evs.add(evp);
}
public int getTypeIndex() {
return typeIndex;
}
public final String getTypeSignature() {
// ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex);
ConstantUtf8 utf8 = (ConstantUtf8)cpool.getConstant(typeIndex/*c.getNameIndex()*/);
return utf8.getBytes();
}
public final String getTypeName() {
return getTypeSignature();// BCELBUG: Should I use this instead? Utility.signatureToString(getTypeSignature());
}
/**
* Returns list of ElementNameValuePair objects
*/
public List getValues() {
return evs;
}
public String toString() {
StringBuffer s = new StringBuffer();
s.append("AnnotationGen:["+getTypeName()+" #"+evs.size()+" {");
for (int i = 0; i<evs.size();i++) {
s.append(evs.get(i));
if (i+1<evs.size()) s.append(",");
}
s.append("}]");
return s.toString();
}
public String toShortString() {
StringBuffer s = new StringBuffer();
s.append("@"+getTypeName()+"(");
for (int i = 0; i<evs.size();i++) {
s.append(evs.get(i));
if (i+1<evs.size()) s.append(",");
}
s.append(")");
return s.toString();
}

private void isRuntimeVisible(boolean b) {
isRuntimeVisible = b;
}
public boolean isRuntimeVisible() {
return isRuntimeVisible;
}
}

+ 87
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ArrayElementValueGen.java View File

@@ -0,0 +1,87 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;


public class ArrayElementValueGen extends ElementValueGen {
// J5TODO: Should we make this an array or a list? A list would be easier to modify ...
private List /*ElementValueGen*/ evalues;
public ArrayElementValueGen(ConstantPoolGen cp) {
super(ARRAY,cp);
evalues = new ArrayList();
}
public ArrayElementValueGen(int type, ElementValueGen[] datums, ConstantPoolGen cpool) {
super(type,cpool);
if (type != ARRAY)
throw new RuntimeException("Only element values of type array can be built with this ctor");
this.evalues = new ArrayList();
for (int i = 0; i < datums.length; i++) {
evalues.add(datums[i]);
}
}

/**
* @param value
* @param cpool
*/
public ArrayElementValueGen(ArrayElementValue value, ConstantPoolGen cpool) {
super(ARRAY,cpool);
evalues = new ArrayList();
ElementValue[] in = value.getElementValuesArray();
for (int i = 0; i < in.length; i++) {
evalues.add(ElementValueGen.copy(in[i],cpool));
}
}

public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 type of value (ARRAY == '[')
dos.writeShort(evalues.size());
for (Iterator iter = evalues.iterator(); iter.hasNext();) {
ElementValueGen element = (ElementValueGen) iter.next();
element.dump(dos);
}
}
public String stringifyValue() {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (Iterator iter = evalues.iterator(); iter.hasNext();) {
ElementValueGen element = (ElementValueGen) iter.next();
sb.append(element.stringifyValue());
if (iter.hasNext()) sb.append(",");
}
sb.append("]");
return sb.toString();
}
public List getElementValues() { return evalues;}
public int getElementValuesSize() { return evalues.size();}

public void addElement(ElementValueGen gen) {
evalues.add(gen);
}
}

+ 59
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ClassElementValueGen.java View File

@@ -0,0 +1,59 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.ConstantClass;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.ObjectType;


public class ClassElementValueGen extends ElementValueGen {
// For primitive types and string type, this points to the value entry in the cpool
// For 'class' this points to the class entry in the cpool
private int idx;
protected ClassElementValueGen(int typeIdx,ConstantPoolGen cpool) {
super(ElementValueGen.CLASS,cpool);
this.idx = typeIdx;
}
public ClassElementValueGen(ObjectType t,ConstantPoolGen cpool) {
super(ElementValueGen.CLASS,cpool);
this.idx = cpool.addClass(t);
}
public int getIndex() {
return idx;
}
public String getClassString() {
ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx);
ConstantUtf8 utf8 = (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex());
return utf8.getBytes();
}
public String stringifyValue() {
return getClassString();
}
public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 kind of value
dos.writeShort(idx);
}
}

+ 70
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ElementNameValuePairGen.java View File

@@ -0,0 +1,70 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;


public class ElementNameValuePairGen {
private int nameIdx;
private ElementValueGen value;
private ConstantPoolGen cpool;

public ElementNameValuePairGen(ElementNameValuePair nvp, ConstantPoolGen cpool) {
this.cpool = cpool;
// J5ASSERT:
// Could assert nvp.getNameString() points to the same thing as cpool.getConstant(nvp.getNameIndex())
nameIdx = nvp.getNameIndex();
value = ElementValueGen.copy(nvp.getValue(),cpool);
}


protected ElementNameValuePairGen(int idx,ElementValueGen value,ConstantPoolGen cpool) {
this.nameIdx = idx;
this.value = value;
this.cpool = cpool;
}
public ElementNameValuePairGen(String name,ElementValueGen value,ConstantPoolGen cpool) {
this.nameIdx = cpool.addUtf8(name);
this.value = value;
this.cpool = cpool;
}
protected void dump(DataOutputStream dos) throws IOException {
dos.writeShort(nameIdx); // u2 name of the element
value.dump(dos);
}
public int getNameIndex() {
return nameIdx;
}
public final String getNameString() {
// ConstantString cu8 = (ConstantString)cpool.getConstant(nameIdx);
return ((ConstantUtf8)cpool.getConstant(nameIdx)).getBytes();
}
public final ElementValueGen getValue() {
return value;
}
public String toString() {
return "ElementNameValuePair:["+getNameString()+"="+value.stringifyValue()+"]";
}
}

+ 137
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/ElementValueGen.java View File

@@ -0,0 +1,137 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;

public abstract class ElementValueGen {

protected int type;
protected ConstantPoolGen cpGen;
protected ElementValueGen(int type,ConstantPoolGen cpGen) {
this.type = type;
this.cpGen = cpGen;
}
public int getElementValueType() {
return type;
}
public abstract String stringifyValue();
public abstract void dump(DataOutputStream dos) throws IOException;
public static final int STRING = 's';
public static final int ENUM_CONSTANT = 'e';
public static final int CLASS = 'c';
public static final int ANNOTATION = '@';
public static final int ARRAY = '[';
public static final int PRIMITIVE_INT = 'I';
public static final int PRIMITIVE_BYTE = 'B';
public static final int PRIMITIVE_CHAR = 'C';
public static final int PRIMITIVE_DOUBLE = 'D';
public static final int PRIMITIVE_FLOAT = 'F';
public static final int PRIMITIVE_LONG = 'J';
public static final int PRIMITIVE_SHORT = 'S';
public static final int PRIMITIVE_BOOLEAN= 'Z';
public static ElementValueGen readElementValue(DataInputStream dis,ConstantPoolGen cpGen) throws IOException {
int type= dis.readUnsignedByte();
switch (type) {
case 'B': // byte
return new SimpleElementValueGen(PRIMITIVE_BYTE,dis.readUnsignedShort(),cpGen);
case 'C': // char
return new SimpleElementValueGen(PRIMITIVE_CHAR,dis.readUnsignedShort(),cpGen);
case 'D': // double
return new SimpleElementValueGen(PRIMITIVE_DOUBLE,dis.readUnsignedShort(),cpGen);
case 'F': // float
return new SimpleElementValueGen(PRIMITIVE_FLOAT,dis.readUnsignedShort(),cpGen);
case 'I': // int
return new SimpleElementValueGen(PRIMITIVE_INT,dis.readUnsignedShort(),cpGen);
case 'J': // long
return new SimpleElementValueGen(PRIMITIVE_LONG,dis.readUnsignedShort(),cpGen);
case 'S': // short
return new SimpleElementValueGen(PRIMITIVE_SHORT,dis.readUnsignedShort(),cpGen);
case 'Z': // boolean
return new SimpleElementValueGen(PRIMITIVE_BOOLEAN,dis.readUnsignedShort(),cpGen);
case 's': // String
return new SimpleElementValueGen(STRING,dis.readUnsignedShort(),cpGen);

case 'e': // Enum constant
return new EnumElementValueGen(dis.readUnsignedShort(),dis.readUnsignedShort(),cpGen);

case 'c': // Class
return new ClassElementValueGen(dis.readUnsignedShort(),cpGen);
//
// case '@': // Annotation
// return new AnnotationElementValueGen(ANNOTATION,Annotation.read(dis,cpGen),cpGen);
//
// case '[': // Array
// int numArrayVals = dis.readUnsignedShort();
// List arrayVals = new ArrayList();
// ElementValue[] evalues = new ElementValue[numArrayVals];
// for (int j=0;j<numArrayVals;j++) {
// evalues[j] = ElementValue.readElementValue(dis,cpGen);
// }
// return new ArrayElementValue(ARRAY,evalues,cpGen);

default:
throw new RuntimeException("Unexpected element value kind in annotation: "+type);
}
}

protected ConstantPoolGen getConstantPool() {
return cpGen;
}

/**
* Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct.
*/
public static ElementValueGen copy(ElementValue value,ConstantPoolGen cpool) {
switch (value.getElementValueType()) {
case 'B': // byte
case 'C': // char
case 'D': // double
case 'F': // float
case 'I': // int
case 'J': // long
case 'S': // short
case 'Z': // boolean
case 's': // String
return new SimpleElementValueGen((SimpleElementValue)value,cpool);
case 'e': // Enum constant
return new EnumElementValueGen((EnumElementValue)value,cpool);

case '@': // Annotation
return new AnnotationElementValueGen((AnnotationElementValue)value,cpool);
case '[': // Array
return new ArrayElementValueGen((ArrayElementValue)value,cpool);

default:
throw new RuntimeException("Not implemented yet! ("+value.getElementValueType()+")");
}
}
}

+ 84
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/EnumElementValueGen.java View File

@@ -0,0 +1,84 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.ConstantClass;
import org.aspectj.apache.bcel.classfile.ConstantString;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.ObjectType;


public class EnumElementValueGen extends ElementValueGen {
// For enum types, these two indices point to the type and value
private int typeIdx;
private int valueIdx;
/**
* This ctor assumes the constant pool already contains the right type and value -
* as indicated by typeIdx and valueIdx. This ctor is used for deserialization
*/
protected EnumElementValueGen(int typeIdx,int valueIdx,ConstantPoolGen cpool) {
super(ElementValueGen.ENUM_CONSTANT,cpool);
if (type != ENUM_CONSTANT)
throw new RuntimeException("Only element values of type enum can be built with this ctor");
this.typeIdx = typeIdx;
this.valueIdx= valueIdx;
}
public EnumElementValueGen(ObjectType t,String value,ConstantPoolGen cpool) {
super(ElementValueGen.ENUM_CONSTANT,cpool);
typeIdx = cpool.addClass(t);
valueIdx= cpool.addString(value);
}

public EnumElementValueGen(EnumElementValue value, ConstantPoolGen cpool) {
super(ENUM_CONSTANT,cpool);
typeIdx = value.getTypeIndex();
valueIdx = value.getValueIndex();
}

public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e')
dos.writeShort(typeIdx); // u2
dos.writeShort(valueIdx); // u2
}
public String stringifyValue() {
ConstantString cu8 = (ConstantString)getConstantPool().getConstant(valueIdx);
return ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
}
// BCELBUG: Should we need to call utility.signatureToString() on the output here?
public String getEnumTypeString() {
ConstantClass cu8 = (ConstantClass)getConstantPool().getConstant(typeIdx);
return ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
// return Utility.signatureToString(cu8.getBytes());
}
public String getEnumValueString() {
ConstantString cu8 = (ConstantString)getConstantPool().getConstant(valueIdx);
return ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
}
public int getValueIndex() { return valueIdx;}
public int getTypeIndex() { return typeIdx; }

}

+ 173
- 0
bcel-builder/src/org/aspectj/apache/bcel/generic/annotation/SimpleElementValueGen.java View File

@@ -0,0 +1,173 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.generic.annotation;

import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.ConstantDouble;
import org.aspectj.apache.bcel.classfile.ConstantFloat;
import org.aspectj.apache.bcel.classfile.ConstantInteger;
import org.aspectj.apache.bcel.classfile.ConstantLong;
import org.aspectj.apache.bcel.classfile.ConstantUtf8;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;


public class SimpleElementValueGen extends ElementValueGen {
// For primitive types and string type, this points to the value entry in the cpGen
// For 'class' this points to the class entry in the cpGen
private int idx;
// ctors for each supported type... type could be inferred but for now lets
// force it to be passed
/**
* Protected ctor used for deserialization, doesn't *put* an entry in the constant pool,
* assumes the one at the supplied index is correct.
*/
protected SimpleElementValueGen(int type,int idx,ConstantPoolGen cpGen) {
super(type,cpGen);
this.idx = idx;
}
public SimpleElementValueGen(int type,ConstantPoolGen cpGen,int value) {
super(type,cpGen);
idx = cpGen.addInteger(value);
}
public SimpleElementValueGen(int type,ConstantPoolGen cpGen,long value) {
super(type,cpGen);
idx = cpGen.addLong(value);
}
public SimpleElementValueGen(int type,ConstantPoolGen cpGen,double value) {
super(type,cpGen);
idx = cpGen.addDouble(value);
}
public SimpleElementValueGen(int type,ConstantPoolGen cpGen,float value) {
super(type,cpGen);
idx = cpGen.addFloat(value);
}

public SimpleElementValueGen(int type,ConstantPoolGen cpGen,short value) {
super(type,cpGen);
idx = cpGen.addInteger(value);
}

public SimpleElementValueGen(int type,ConstantPoolGen cpGen,byte value) {
super(type,cpGen);
idx = cpGen.addInteger(value);
}

public SimpleElementValueGen(int type,ConstantPoolGen cpGen,char value) {
super(type,cpGen);
idx = cpGen.addInteger(value);
}

public SimpleElementValueGen(int type,ConstantPoolGen cpGen,boolean value) {
super(type,cpGen);
if (value) idx = cpGen.addInteger(1);
else idx = cpGen.addInteger(0);
}
public SimpleElementValueGen(int type,ConstantPoolGen cpGen,String value) {
super(type,cpGen);
idx = cpGen.addUtf8(value);
}
public SimpleElementValueGen(SimpleElementValue value,ConstantPoolGen cpool) {
super(value.getElementValueType(),cpool);
// J5ASSERT: Could assert value.stringifyValue() is the same as
// cpool.getConstant(SimpleElementValuevalue.getIndex())
idx = value.getIndex();
}

public int getIndex() {
return idx;
}

public String getValueString() {
if (type != STRING)
throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue");
ConstantUtf8 c = (ConstantUtf8)cpGen.getConstant(idx);
return c.getBytes();
}
public int getValueInt() {
if (type != PRIMITIVE_INT)
throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue");
ConstantInteger c = (ConstantInteger)cpGen.getConstant(idx);
return c.getBytes();
}
// Whatever kind of value it is, return it as a string
public String stringifyValue() {
switch (type) {
case PRIMITIVE_INT:
ConstantInteger c = (ConstantInteger)cpGen.getConstant(idx);
return Integer.toString(c.getBytes());
case PRIMITIVE_LONG:
ConstantLong j = (ConstantLong)cpGen.getConstant(idx);
return Long.toString(j.getBytes());
case PRIMITIVE_DOUBLE:
ConstantDouble d = (ConstantDouble)cpGen.getConstant(idx);
return Double.toString(d.getBytes());
case PRIMITIVE_FLOAT:
ConstantFloat f = (ConstantFloat)cpGen.getConstant(idx);
return Float.toString(f.getBytes());
case PRIMITIVE_SHORT:
ConstantInteger s = (ConstantInteger)cpGen.getConstant(idx);
return Integer.toString(s.getBytes());
case PRIMITIVE_BYTE:
ConstantInteger b = (ConstantInteger)cpGen.getConstant(idx);
return Integer.toString(b.getBytes());
case PRIMITIVE_CHAR:
ConstantInteger ch = (ConstantInteger)cpGen.getConstant(idx);
return Integer.toString(ch.getBytes());
case PRIMITIVE_BOOLEAN:
ConstantInteger bo = (ConstantInteger)cpGen.getConstant(idx);
if (bo.getBytes() == 0) return "false";
if (bo.getBytes() != 0) return "true";
case STRING:
ConstantUtf8 cu8 = (ConstantUtf8)cpGen.getConstant(idx);
return cu8.getBytes();
default:
throw new RuntimeException("SimpleElementValueGen class does not know how to stringify type "+type);
}
}
public void dump(DataOutputStream dos) throws IOException {
dos.writeByte(type); // u1 kind of value
switch (type) {
case PRIMITIVE_INT:
case PRIMITIVE_BYTE:
case PRIMITIVE_CHAR:
case PRIMITIVE_FLOAT:
case PRIMITIVE_LONG:
case PRIMITIVE_BOOLEAN:
case PRIMITIVE_SHORT:
case PRIMITIVE_DOUBLE:
case STRING:
dos.writeShort(idx);
break;
default:
throw new RuntimeException("SimpleElementValueGen doesnt know how to write out type "+type);
}
}
}

+ 54
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AllTests.java View File

@@ -0,0 +1,54 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.aspectj.apache.bcel.classfile.tests.AnnotationAccessFlagTest;
import org.aspectj.apache.bcel.classfile.tests.AnnotationDefaultAttributeTest;
import org.aspectj.apache.bcel.classfile.tests.ElementValueGenTest;
import org.aspectj.apache.bcel.classfile.tests.EnclosingMethodAttributeTest;
import org.aspectj.apache.bcel.classfile.tests.EnumAccessFlagTest;
import org.aspectj.apache.bcel.classfile.tests.FieldAnnotationsTest;
import org.aspectj.apache.bcel.classfile.tests.GeneratingAnnotatedClassesTest;
import org.aspectj.apache.bcel.classfile.tests.LocalVariableTypeTableTest;
import org.aspectj.apache.bcel.classfile.tests.MethodAnnotationsTest;
import org.aspectj.apache.bcel.classfile.tests.RuntimeVisibleAnnotationAttributeTest;
import org.aspectj.apache.bcel.classfile.tests.RuntimeVisibleParameterAnnotationAttributeTest;
import org.aspectj.apache.bcel.classfile.tests.VarargsTest;

public class AllTests {

public static Test suite() {
TestSuite suite = new TestSuite("Tests for BCEL Java5 support");
//$JUnit-BEGIN$
suite
.addTestSuite(RuntimeVisibleParameterAnnotationAttributeTest.class);
suite.addTestSuite(AnnotationDefaultAttributeTest.class);
suite.addTestSuite(EnclosingMethodAttributeTest.class);
suite.addTestSuite(MethodAnnotationsTest.class);
suite.addTestSuite(RuntimeVisibleAnnotationAttributeTest.class);
suite.addTestSuite(EnumAccessFlagTest.class);
suite.addTestSuite(LocalVariableTypeTableTest.class);
suite.addTestSuite(VarargsTest.class);
suite.addTestSuite(AnnotationAccessFlagTest.class);
suite.addTestSuite(ElementValueGenTest.class);
suite.addTestSuite(FieldAnnotationsTest.class);
suite.addTestSuite(AnnotationGenTest.class);
suite.addTestSuite(ParameterAnnotationsTest.class);
suite.addTestSuite(GeneratingAnnotatedClassesTest.class);
//$JUnit-END$
return suite;
}
}

+ 55
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AnnotationAccessFlagTest.java View File

@@ -0,0 +1,55 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;

import junit.framework.TestCase;

import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.util.ClassPath;
import org.aspectj.apache.bcel.util.SyntheticRepository;

public class AnnotationAccessFlagTest extends TestCase {
private boolean verbose = false;

protected void setUp() throws Exception {
super.setUp();
}
/**
* If you write an annotation and compile it, the class file generated should be
* marked as an annotation type - which is detectable through BCEL.
*/
public void testAnnotationClassSaysItIs() throws ClassNotFoundException {
ClassPath cp =
new ClassPath("testdata"+File.separator+"testcode.jar"+File.pathSeparator+System.getProperty("java.class.path"));
SyntheticRepository repos = SyntheticRepository.getInstance(cp);
JavaClass clazz = repos.loadClass("SimpleAnnotation");
ConstantPool pool = clazz.getConstantPool();
assertTrue("Expected SimpleAnnotation class to say it was an annotation - but it didn't !",
clazz.isAnnotation());
clazz = repos.loadClass("SimpleClass");
assertTrue("Expected SimpleClass class to say it was not an annotation - but it didn't !",
!clazz.isAnnotation());
}

protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 49
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AnnotationDefaultAttributeTest.java View File

@@ -0,0 +1,49 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import org.aspectj.apache.bcel.classfile.AnnotationDefault;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;

public class AnnotationDefaultAttributeTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}

/**
* For values in an annotation that have default values, we should be able to
* query the AnnotationDefault attribute against the method to discover the
* default value that was originally declared.
*/
public void testMethodAnnotations() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("SimpleAnnotation");
Method m = getMethod(clazz,"fruit");
AnnotationDefault a = (AnnotationDefault) findAttribute("AnnotationDefault",m.getAttributes());
SimpleElementValue val = (SimpleElementValue) a.getElementValue();
assertTrue("Should be STRING but is "+val.getElementValueType(),
val.getElementValueType()==ElementValue.STRING);
assertTrue("Should have default of bananas but default is "+val.getValueString(),
val.getValueString().equals("bananas"));
}

protected void tearDown() throws Exception {
super.tearDown();
}
}

+ 122
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/AnnotationGenTest.java View File

@@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (c) 2004 IBM All rights reserved. This program and the accompanying
* materials are made available under the terms of the Common Public License
* v1.0 which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors: Andy Clement - initial implementation
******************************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.generic.ClassGen;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
import org.aspectj.apache.bcel.generic.annotation.ElementNameValuePairGen;
import org.aspectj.apache.bcel.generic.annotation.ElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.SimpleElementValueGen;

public class AnnotationGenTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}

private ClassGen createClassGen(String classname) {
return new ClassGen(classname, "java.lang.Object",
"<generated>", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
}

/**
* Programmatically construct an mutable annotation (AnnotationGen) object.
*/
public void testConstructMutableAnnotation() {
// Create the containing class
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
// Create the simple primitive value '4' of type 'int'
SimpleElementValueGen evg =
new SimpleElementValueGen(ElementValueGen.PRIMITIVE_INT,cp,4);
// Give it a name, call it 'id'
ElementNameValuePairGen nvGen = new ElementNameValuePairGen("id",evg,cp);
// Check it looks right
assertTrue("Should include string 'id=4' but says: "+nvGen.toString(),
nvGen.toString().indexOf("id=4")!=-1);
ObjectType t = new ObjectType("SimpleAnnotation");
List elements = new ArrayList();
elements.add(nvGen);
// Build an annotation of type 'SimpleAnnotation' with 'id=4' as the only value :)
AnnotationGen a = new AnnotationGen(t,elements,true,cp);
// Check we can save and load it ok
checkSerialize(a,cp);
}
////
// Helper methods
private void checkSerialize(AnnotationGen a,ConstantPoolGen cpg) {
try {
String beforeName = a.getTypeName();
List beforeValues = a.getValues();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
a.dump(dos);
dos.flush();
dos.close();
byte[] bs = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bs);
DataInputStream dis = new DataInputStream(bais);
AnnotationGen annAfter = AnnotationGen.read(dis,cpg,a.isRuntimeVisible());
dis.close();
String afterName = annAfter.getTypeName();
List afterValues = annAfter.getValues();
if (!beforeName.equals(afterName)) {
fail("Deserialization failed: before type='"+beforeName+"' after type='"+afterName+"'");
}
if (a.getValues().size()!=annAfter.getValues().size()) {
fail("Different numbers of element name value pairs?? "+a.getValues().size()+"!="+annAfter.getValues().size());
}
for (int i=0;i<a.getValues().size();i++) {
ElementNameValuePairGen beforeElement = (ElementNameValuePairGen) a.getValues().get(i);
ElementNameValuePairGen afterElement = (ElementNameValuePairGen) annAfter.getValues().get(i);
if (!beforeElement.getNameString().equals(afterElement.getNameString())) {
fail("Different names?? "+beforeElement.getNameString()+"!="+afterElement.getNameString());
}
}
} catch (IOException ioe) {
fail("Unexpected exception whilst checking serialization: "+ioe);
}
}

protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 150
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java View File

@@ -0,0 +1,150 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation {date}
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
import org.aspectj.apache.bcel.generic.annotation.ElementNameValuePairGen;
import org.aspectj.apache.bcel.generic.annotation.ElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.SimpleElementValueGen;
import org.aspectj.apache.bcel.util.ClassPath;
import org.aspectj.apache.bcel.util.SyntheticRepository;

import junit.framework.TestCase;

/**
* Super class for the Java5 tests, includes various helper methods.
*/

public class BcelTestCase extends TestCase {

private boolean verbose = false;

protected File createTestdataFile(String name) {
return new File("testdata"+File.separator+name);
}
protected JavaClass getClassFromJar(String clazzname) throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
return repos.loadClass(clazzname);
}
protected Method getMethod(JavaClass cl,String methodname) {
Method[] methods = cl.getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName().equals(methodname)) {
return m;
}
}
return null;
}
protected boolean wipe(String name) {
return new File("testdata"+File.separator+name).delete();
}
protected boolean wipe(String dir, String name) {
boolean b = wipe(dir+File.separator+name);
String[] files = new File(dir).list();
if (files==null || files.length==0) {
new File(dir).delete(); // Why does this not succeed? stupid thing
}
return b;
}

public SyntheticRepository createRepos(String cpentry) {
ClassPath cp = new ClassPath(
"testdata"+File.separator+cpentry+File.pathSeparator+
System.getProperty("java.class.path"));
return SyntheticRepository.getInstance(cp);
}
protected Attribute[] findAttribute(String name, JavaClass clazz) {
Attribute[] all = clazz.getAttributes();
List chosenAttrsList = new ArrayList();
for (int i = 0; i < all.length; i++) {
if (verbose) System.err.println("Attribute: "+all[i].getName());
if (all[i].getName().equals(name)) chosenAttrsList.add(all[i]);
}
return (Attribute[])chosenAttrsList.toArray(new Attribute[]{});
}
protected Attribute findAttribute(String name, Attribute[] all) {
List chosenAttrsList = new ArrayList();
for (int i = 0; i < all.length; i++) {
if (verbose) System.err.println("Attribute: "+all[i].getName());
if (all[i].getName().equals(name)) chosenAttrsList.add(all[i]);
}
assertTrue("Should be one match: "+chosenAttrsList.size(),chosenAttrsList.size()==1);
return (Attribute)chosenAttrsList.get(0);
}

protected String dumpAnnotations(Annotation[] as) {
StringBuffer result = new StringBuffer();
result.append("[");
for (int i = 0; i < as.length; i++) {
Annotation annotation = as[i];
result.append(annotation.toShortString());
if (i+1<as.length) result.append(",");
}
result.append("]");
return result.toString();
}
protected String dumpAnnotations(AnnotationGen[] as) {
StringBuffer result = new StringBuffer();
result.append("[");
for (int i = 0; i < as.length; i++) {
AnnotationGen annotation = as[i];
result.append(annotation.toShortString());
if (i+1<as.length) result.append(",");
}
result.append("]");
return result.toString();
}
protected String dumpAttributes(Attribute[] as) {
StringBuffer result = new StringBuffer();
result.append("AttributeArray:[");
for (int i = 0; i < as.length; i++) {
Attribute attr = as[i];
result.append(attr.toString());
if (i+1<as.length) result.append(",");
}
result.append("]");
return result.toString();
}

public AnnotationGen createFruitAnnotation(ConstantPoolGen cp, String aFruit, boolean visibility) {
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.STRING,cp,aFruit);
ElementNameValuePairGen nvGen = new ElementNameValuePairGen("fruit",evg,cp);
ObjectType t = new ObjectType("SimpleStringAnnotation");
List elements = new ArrayList();
elements.add(nvGen);
return new AnnotationGen(t,elements,visibility,cp);
}

}

+ 227
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ElementValueGenTest.java View File

@@ -0,0 +1,227 @@
/*******************************************************************************
* Copyright (c) 2004 IBM All rights reserved. This program and the accompanying
* materials are made available under the terms of the Common Public License
* v1.0 which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors: Andy Clement - initial implementation
******************************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.generic.ClassGen;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.annotation.ClassElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.ElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.EnumElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.SimpleElementValueGen;

public class ElementValueGenTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}

private ClassGen createClassGen(String classname) {
return new ClassGen(classname, "java.lang.Object",
"<generated>", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
}

////
// Create primitive element values

public void testCreateIntegerElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_INT,cp,555);
// Creation of an element like that should leave a new entry in the cpool
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+cp.lookupInteger(555),
evg.getIndex()==cp.lookupInteger(555));
checkSerialize(evg,cp);
}

public void testCreateFloatElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_FLOAT,cp,111.222f);
// Creation of an element like that should leave a new entry in the cpool
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+cp.lookupFloat(111.222f),
evg.getIndex()==cp.lookupFloat(111.222f));
checkSerialize(evg,cp);
}
public void testCreateDoubleElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_DOUBLE,cp,333.44);
// Creation of an element like that should leave a new entry in the cpool
int idx = cp.lookupDouble(333.44);
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+idx,
evg.getIndex()==idx);
checkSerialize(evg,cp);
}
public void testCreateLongElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_LONG,cp,3334455L);
// Creation of an element like that should leave a new entry in the cpool
int idx = cp.lookupLong(3334455L);
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+idx,
evg.getIndex()==idx);
checkSerialize(evg,cp);
}

public void testCreateCharElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_CHAR,cp,(char)'t');
// Creation of an element like that should leave a new entry in the cpool
int idx = cp.lookupInteger((char)'t');
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+idx,
evg.getIndex()==idx);
checkSerialize(evg,cp);
}
public void testCreateByteElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_CHAR,cp,(byte)'z');
// Creation of an element like that should leave a new entry in the cpool
int idx = cp.lookupInteger((byte)'z');
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+idx,
evg.getIndex()==idx);
checkSerialize(evg,cp);
}

public void testCreateBooleanElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_BOOLEAN,cp,true);
// Creation of an element like that should leave a new entry in the cpool
int idx = cp.lookupInteger(1); // 1 == true
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+idx,
evg.getIndex()==idx);
checkSerialize(evg,cp);
}

public void testCreateShortElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_SHORT,cp,(short)42);
// Creation of an element like that should leave a new entry in the cpool
int idx = cp.lookupInteger(42);
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+idx,
evg.getIndex()==idx);
checkSerialize(evg,cp);
}
////
// Create string element values

public void testCreateStringElementValue() {

// Create HelloWorld
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.STRING,cp,"hello");
// Creation of an element like that should leave a new entry in the cpool
assertTrue("Should have the same index in the constantpool but "+evg.getIndex()+"!="+cp.lookupUtf8("hello"),
evg.getIndex()==cp.lookupUtf8("hello"));
checkSerialize(evg,cp);
}
////
// Create enum element value
public void testCreateEnumElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();

ObjectType enumType = new ObjectType("SimpleEnum"); // Supports rainbow :)
EnumElementValueGen evg = new EnumElementValueGen(enumType,"Red",cp);
// Creation of an element like that should leave a new entry in the cpool
assertTrue("The new ElementValue value index should match the contents of the constantpool but "+
evg.getValueIndex()+"!="+cp.lookupString("Red"),
evg.getValueIndex()==cp.lookupString("Red"));
//BCELBUG: Should the class signature or class name be in the constant pool? (see note in ConstantPool)
// assertTrue("The new ElementValue type index should match the contents of the constantpool but "+
// evg.getTypeIndex()+"!="+cp.lookupClass(enumType.getSignature()),
// evg.getTypeIndex()==cp.lookupClass(enumType.getSignature()));

checkSerialize(evg,cp);
}
////
// Create class element value
public void testCreateClassElementValue() {
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
ObjectType classType = new ObjectType("java.lang.Integer");
ClassElementValueGen evg = new ClassElementValueGen(classType,cp);
assertTrue("Unexpected value for contained class: '"+evg.getClassString()+"'",
evg.getClassString().indexOf("Integer")!=-1);

checkSerialize(evg,cp);
}
////
// Helper methods
private void checkSerialize(ElementValueGen evgBefore,ConstantPoolGen cpg) {
try {
String beforeValue = evgBefore.stringifyValue();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
evgBefore.dump(dos);
dos.flush();
dos.close();
byte[] bs = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bs);
DataInputStream dis = new DataInputStream(bais);
ElementValueGen evgAfter = ElementValueGen.readElementValue(dis,cpg);
dis.close();
String afterValue = evgAfter.stringifyValue();
if (!beforeValue.equals(afterValue)) {
fail("Deserialization failed: before='"+beforeValue+"' after='"+afterValue+"'");
}
} catch (IOException ioe) {
fail("Unexpected exception whilst checking serialization: "+ioe);
}
}

protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 104
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnclosingMethodAttributeTest.java View File

@@ -0,0 +1,104 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.io.IOException;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.EnclosingMethod;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class EnclosingMethodAttributeTest extends BcelTestCase {
protected void setUp() throws Exception {
super.setUp();
}
/**
* Verify for an inner class declared inside the 'main' method that the enclosing method
* attribute is set correctly.
*/
public void testCheckMethodLevelNamedInnerClass() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AttributeTestClassEM01$1S");
ConstantPool pool = clazz.getConstantPool();
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length,
encMethodAttrs.length==1);
EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getBytes(pool);
String enclosingMethodName= em.getEnclosingMethod().getName(pool);
assertTrue("Expected class name to be 'AttributeTestClassEM01' but was "+enclosingClassName,
enclosingClassName.equals("AttributeTestClassEM01"));
assertTrue("Expected method name to be 'main' but was "+enclosingMethodName,
enclosingMethodName.equals("main"));
}
/**
* Verify for an inner class declared at the type level that the EnclosingMethod attribute
* is set correctly (i.e. to a null value)
*/
public void testCheckClassLevelNamedInnerClass() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AttributeTestClassEM02$1");
ConstantPool pool = clazz.getConstantPool();
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length,
encMethodAttrs.length==1);
EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getBytes(pool);
assertTrue("The class is not within a method, so method_index should be null, but it is "+
em.getEnclosingMethodIndex(),em.getEnclosingMethodIndex() == 0);
assertTrue("Expected class name to be 'AttributeTestClassEM02' but was "+enclosingClassName,
enclosingClassName.equals("AttributeTestClassEM02"));
}
/**
* Check that we can save and load the attribute correctly.
*/
public void testAttributeSerializtion() throws ClassNotFoundException,IOException {
// Read in the class
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AttributeTestClassEM02$1");
ConstantPool pool = clazz.getConstantPool();
Attribute[] encMethodAttrs = findAttribute("EnclosingMethod",clazz);
assertTrue("Expected 1 EnclosingMethod attribute but found "+encMethodAttrs.length,
encMethodAttrs.length==1);
// Write it out
File tfile = createTestdataFile("AttributeTestClassEM02$1.class");
clazz.dump(tfile);
// Read in the new version and check it is OK
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AttributeTestClassEM02$1");
EnclosingMethod em = (EnclosingMethod)encMethodAttrs[0];
String enclosingClassName = em.getEnclosingClass().getBytes(pool);
assertTrue("The class is not within a method, so method_index should be null, but it is "+
em.getEnclosingMethodIndex(),em.getEnclosingMethodIndex() == 0);
assertTrue("Expected class name to be 'AttributeTestClassEM02' but was "+enclosingClassName,
enclosingClassName.equals("AttributeTestClassEM02"));
assertTrue(tfile.delete());
}

protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 56
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/EnumAccessFlagTest.java View File

@@ -0,0 +1,56 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;

import junit.framework.TestCase;

import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.util.ClassPath;
import org.aspectj.apache.bcel.util.SyntheticRepository;

public class EnumAccessFlagTest extends TestCase {
private boolean verbose = false;

protected void setUp() throws Exception {
super.setUp();
}
/**
* An enumerated type, once compiled, should result in a class file that
* is marked such that we can determine from the access flags (through BCEL) that
* it was originally an enum type declaration.
*/
public void testEnumClassSaysItIs() throws ClassNotFoundException {
ClassPath cp =
new ClassPath("testdata"+File.separator+"testcode.jar"+File.pathSeparator+System.getProperty("java.class.path"));
SyntheticRepository repos = SyntheticRepository.getInstance(cp);
JavaClass clazz = repos.loadClass("SimpleEnum");
ConstantPool pool = clazz.getConstantPool();
assertTrue("Expected SimpleEnum class to say it was an enum - but it didn't !",
clazz.isEnum());
clazz = repos.loadClass("SimpleClass");
assertTrue("Expected SimpleClass class to say it was not an enum - but it didn't !",
!clazz.isEnum());
}

protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 147
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/FieldAnnotationsTest.java View File

@@ -0,0 +1,147 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.generic.ClassGen;
import org.aspectj.apache.bcel.generic.FieldGen;
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class FieldAnnotationsTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}
/**
* Check field annotations are retrievable.
*/
public void testFieldAnnotations() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("AnnotatedFields");
checkAnnotatedField(clazz,"i","SimpleAnnotation","id","1");
checkAnnotatedField(clazz,"s","SimpleAnnotation","id","2");

}

/**
* Check field annotations (de)serialize ok.
*/
public void testFieldAnnotationsReadWrite() throws ClassNotFoundException,IOException {
JavaClass clazz = getClassFromJar("AnnotatedFields");
checkAnnotatedField(clazz,"i","SimpleAnnotation","id","1");
checkAnnotatedField(clazz,"s","SimpleAnnotation","id","2");
// Write it out
File tfile = createTestdataFile("AnnotatedFields.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedFields");
checkAnnotatedField(clazz,"i","SimpleAnnotation","id","1");
checkAnnotatedField(clazz,"s","SimpleAnnotation","id","2");

assertTrue(tfile.delete());
}

/**
* Check we can load in a class, modify its field annotations, save it, reload it and
* everything is correct.
*/
public void testFieldAnnotationsModification() throws ClassNotFoundException, IOException {
boolean dbg = false;
JavaClass clazz = getClassFromJar("AnnotatedFields");
ClassGen clg = new ClassGen(clazz);
Field f = clg.getFields()[0];
if (dbg) System.err.println("Field in freshly constructed class is: "+f);
if (dbg) System.err.println("Annotations on field are: "+dumpAnnotations(f.getAnnotations()));
AnnotationGen fruitBasedAnnotation = createFruitAnnotation(clg.getConstantPool(),"Tomato",false);
FieldGen fg = new FieldGen(f,clg.getConstantPool());
if (dbg) System.err.println("Adding annotation to the field");
fg.addAnnotation(fruitBasedAnnotation);
if (dbg) System.err.println("FieldGen (mutable field) is "+fg);
if (dbg) System.err.println("with annotations: "+dumpAnnotations(fg.getAnnotations()));

if (dbg) System.err.println("Replacing original field with new field that has extra annotation");
clg.removeField(f);
clg.addField(fg.getField());
f = clg.getFields()[1]; // there are two fields in the class, removing and readding has changed the order
// so this time index [1] is the 'int i' field
if (dbg) System.err.println("Field now looks like this: "+f);
if (dbg) System.err.println("With annotations: "+dumpAnnotations(f.getAnnotations()));
assertTrue("Should be 2 annotations on this field, but there are "+f.getAnnotations().length,f.getAnnotations().length==2);
}
// helper methods
public void checkAnnotatedField(JavaClass clazz,String fieldname,
String annotationName,String annotationElementName,String annotationElementValue) {
Field[] fields = clazz.getFields();

for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
Annotation[] fieldAnnotations = f.getAnnotations();
if (f.getName().equals(fieldname)) {
checkAnnotation(fieldAnnotations[0],annotationName,annotationElementName,annotationElementValue);
}
}
}
private void checkAnnotation(Annotation a,String name,String elementname,String elementvalue) {
assertTrue("Expected annotation to have name "+name+" but it had name "+a.getTypeName(),
a.getTypeName().equals(name));
assertTrue("Expected annotation to have one element but it had "+a.getValues().size(),a.getValues().size()==1);
ElementNameValuePair envp = (ElementNameValuePair)a.getValues().get(0);
assertTrue("Expected element name "+elementname+" but was "+envp.getNameString(),
elementname.equals(envp.getNameString()));
assertTrue("Expected element value "+elementvalue+" but was "+envp.getValue().stringifyValue(),
elementvalue.equals(envp.getValue().stringifyValue()));
}

// helper methods
public void checkValue(Annotation a,String name,String tostring) {
for (Iterator i = a.getValues().iterator(); i.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) i.next();
if (element.getNameString().equals(name)) {
if (!element.getValue().stringifyValue().equals(tostring)) {
fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
}
return;
}
}
fail("Didnt find named element "+name);
}

protected void tearDown() throws Exception {
super.tearDown();
}
}

+ 633
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/GeneratingAnnotatedClassesTest.java View File

@@ -0,0 +1,633 @@
/*******************************************************************************
* Copyright (c) 2004 IBM All rights reserved. This program and the accompanying
* materials are made available under the terms of the Common Public License
* v1.0 which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors: Andy Clement - initial implementation
******************************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.generic.ALOAD;
import org.aspectj.apache.bcel.generic.ASTORE;
import org.aspectj.apache.bcel.generic.ArrayType;
import org.aspectj.apache.bcel.generic.ClassGen;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.GOTO;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.LocalVariableGen;
import org.aspectj.apache.bcel.generic.MethodGen;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.PUSH;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.apache.bcel.generic.annotation.AnnotationElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
import org.aspectj.apache.bcel.generic.annotation.ArrayElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.ElementNameValuePairGen;
import org.aspectj.apache.bcel.generic.annotation.ElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.SimpleElementValueGen;
import org.aspectj.apache.bcel.util.SyntheticRepository;

/**
* The program that some of the tests generate looks like this:
public class HelloWorld {
public static void main(String[] argv) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String name = null;
try {
name = "Andy";
} catch(IOException e) { return; }
System.out.println("Hello, " + name);
}
}
*
*/
public class GeneratingAnnotatedClassesTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}

/*
* Steps in the test:
* 1) Programmatically construct the HelloWorld program
* 2) Add two simple annotations at the class level
* 3) Save the class to disk
* 4) Reload the class using the 'static' variant of the BCEL classes
* 5) Check the attributes are OK
*/
public void testGenerateClassLevelAnnotations() throws ClassNotFoundException {

// Create HelloWorld
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();

cg.addAnnotation(createSimpleVisibleAnnotation(cp));
cg.addAnnotation(createSimpleInvisibleAnnotation(cp));

buildClassContents(cg, cp, il);

dumpClass(cg, "HelloWorld.class");
JavaClass jc = getClassFrom(".","HelloWorld");
Annotation[] as = jc.getAnnotations();
assertTrue("Should be two annotations but found "+as.length,as.length==2);
Annotation one = as[0];
Annotation two = as[1];
assertTrue("Name of annotation 1 should be SimpleAnnotation but it is "+as[0].getTypeName(),
as[0].getTypeName().equals("SimpleAnnotation"));
assertTrue("Name of annotation 2 should be SimpleAnnotation but it is "+as[1].getTypeName(),
as[1].getTypeName().equals("SimpleAnnotation"));
List vals = as[0].getValues();
ElementNameValuePair nvp = (ElementNameValuePair) vals.get(0);
assertTrue("Name of element in SimpleAnnotation should be 'id' but it is "+
nvp.getNameString(),nvp.getNameString().equals("id"));
ElementValue ev = nvp.getValue();
assertTrue("Type of element value should be int but it is "+ev.getElementValueType(),
ev.getElementValueType()==ElementValue.PRIMITIVE_INT);
assertTrue("Value of element should be 4 but it is "+ev.stringifyValue(),
ev.stringifyValue().equals("4"));
assertTrue(createTestdataFile("HelloWorld.class").delete());
}

/**
* Just check that we can dump a class that has a method
* annotation on it and it is still there when we read it back in
*/
public void testGenerateMethodLevelAnnotations1() throws ClassNotFoundException {
// Create HelloWorld
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();

buildClassContentsWithAnnotatedMethods(cg, cp, il);
// Check annotation is OK
int i = cg.getMethods()[0].getAnnotations().length;
assertTrue("Prior to dumping, main method should have 1 annotation but has "+i,i==1);
dumpClass(cg, "temp1"+File.separator+"HelloWorld.class");
JavaClass jc2 = getClassFrom("temp1","HelloWorld");
// Check annotation is OK
i = jc2.getMethods()[0].getAnnotations().length;
assertTrue("JavaClass should say 1 annotation on main method but says "+i,i==1);

ClassGen cg2 = new ClassGen(jc2);

// Check it now it is a ClassGen
Method[] m = cg2.getMethods();
i = m[0].getAnnotations().length;
assertTrue("The main 'Method' should have one annotation but has "+i,i==1);
MethodGen mg = new MethodGen(m[0],cg2.getClassName(),cg2.getConstantPool());

// Check it finally when the Method is changed to a MethodGen
i = mg.getAnnotations().length;
assertTrue("The main 'MethodGen' should have one annotation but has "+i,i==1);
assertTrue(wipe("temp1"+File.separator+"HelloWorld.class"));
}

/**
* Going further than the last test - when we reload the method back in, let's change it (adding a new
* annotation) and then store that, read it back in and verify both annotations are there !
*/
public void testGenerateMethodLevelAnnotations2() throws ClassNotFoundException {
// Create HelloWorld
ClassGen cg = createClassGen("HelloWorld");
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();

buildClassContentsWithAnnotatedMethods(cg, cp, il);
dumpClass(cg,"temp2","HelloWorld.class");

JavaClass jc2 = getClassFrom("temp2","HelloWorld");
ClassGen cg2 = new ClassGen(jc2);

// Main method after reading the class back in
Method mainMethod1 = jc2.getMethods()[0];
assertTrue("The 'Method' should have one annotations but has "+mainMethod1.getAnnotations().length,
mainMethod1.getAnnotations().length==1);
MethodGen mainMethod2 = new MethodGen(mainMethod1,cg2.getClassName(),cg2.getConstantPool());

assertTrue("The 'MethodGen' should have one annotations but has "+mainMethod2.getAnnotations().length,
mainMethod2.getAnnotations().length==1);
mainMethod2.addAnnotation(createFruitAnnotation(cg2.getConstantPool(),"Pear"));
cg2.removeMethod(mainMethod1);
cg2.addMethod(mainMethod2.getMethod());

dumpClass(cg2,"temp3","HelloWorld.class");
JavaClass jc3 = getClassFrom("temp3","HelloWorld");
ClassGen cg3 = new ClassGen(jc3);
Method mainMethod3 = cg3.getMethods()[1];
int i = mainMethod3.getAnnotations().length;
assertTrue("The 'Method' should now have two annotations but has "+i,i==2);

assertTrue(wipe("temp2","HelloWorld.class"));
assertTrue(wipe("temp3","HelloWorld.class"));
}

//J5TODO: Need to add deleteFile calls to many of these tests
/**
* Transform simple class from an immutable to a mutable object.
*/
public void testTransformClassToClassGen_SimpleTypes() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","SimpleAnnotatedClass");
ClassGen cgen = new ClassGen(jc);
// Check annotations are correctly preserved
AnnotationGen[] annotations = cgen.getAnnotations();
assertTrue("Expected one annotation but found "+annotations.length,
annotations.length==1);
}
/**
* Transform simple class from an immutable to a mutable object. The class is
* annotated with an annotation that uses an enum.
*/
public void testTransformClassToClassGen_EnumType() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","AnnotatedWithEnumClass");
ClassGen cgen = new ClassGen(jc);
// Check annotations are correctly preserved
AnnotationGen[] annotations = cgen.getAnnotations();
assertTrue("Expected one annotation but found "+annotations.length,
annotations.length==1);
}
/**
* Transform simple class from an immutable to a mutable object. The class is
* annotated with an annotation that uses an array of SimpleAnnotations.
*/
public void testTransformClassToClassGen_ArrayAndAnnotationTypes() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","AnnotatedWithCombinedAnnotation");
ClassGen cgen = new ClassGen(jc);
// Check annotations are correctly preserved
AnnotationGen[] annotations = cgen.getAnnotations();
assertTrue("Expected one annotation but found "+annotations.length,
annotations.length==1);
AnnotationGen a = annotations[0];
assertTrue("That annotation should only have one value but has "+a.getValues().size(),a.getValues().size()==1);
ElementNameValuePairGen nvp = (ElementNameValuePairGen)a.getValues().get(0);
ElementValueGen value = (ElementValueGen)nvp.getValue();
assertTrue("Value should be ArrayElementValueGen but is "+value,value instanceof ArrayElementValueGen);
ArrayElementValueGen arrayValue = (ArrayElementValueGen)value;
assertTrue("Array value should be size one but is "+arrayValue.getElementValuesSize(),
arrayValue.getElementValuesSize()==1);
ElementValueGen innerValue = (ElementValueGen)arrayValue.getElementValues().get(0);
assertTrue("Value in the array should be AnnotationElementValueGen but is "+innerValue,
innerValue instanceof AnnotationElementValueGen);
AnnotationElementValueGen innerAnnotationValue = (AnnotationElementValueGen)innerValue;
assertTrue("Should be called LSimpleAnnotation; but is called: "+innerAnnotationValue.getAnnotation().getTypeName(),
innerAnnotationValue.getAnnotation().getTypeSignature().equals("LSimpleAnnotation;"));
}

/**
* Transform complex class from an immutable to a mutable object.
*/
public void testTransformComplexClassToClassGen() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","ComplexAnnotatedClass");
ClassGen cgen = new ClassGen(jc);
// Check annotations are correctly preserved
AnnotationGen[] annotations = cgen.getAnnotations();
assertTrue("Expected one annotation but found "+annotations.length,
annotations.length==1);
List l = annotations[0].getValues();
boolean found = false;
for (Iterator iter = l.iterator(); iter.hasNext();) {
ElementNameValuePairGen element = (ElementNameValuePairGen) iter.next();
if (element.getNameString().equals("dval")) {
if (((SimpleElementValueGen)element.getValue()).stringifyValue().equals("33.4"))
found = true;
}
}
assertTrue("Did not find double annotation value with value 33.4",found);
}


/**
* Load a class in and modify it with a new attribute - A SimpleAnnotation annotation
*/
public void testModifyingClasses1() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","SimpleAnnotatedClass");
ClassGen cgen = new ClassGen(jc);
ConstantPoolGen cp = cgen.getConstantPool();
cgen.addAnnotation(createFruitAnnotation(cp,"Pineapple"));
assertTrue("Should now have two annotations but has "+cgen.getAnnotations().length,
cgen.getAnnotations().length==2);
dumpClass(cgen,"SimpleAnnotatedClass.class");
assertTrue(wipe("SimpleAnnotatedClass.class"));
}
/**
* Load a class in and modify it with a new attribute - A ComplexAnnotation annotation
*/
public void testModifyingClasses2() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","SimpleAnnotatedClass");
ClassGen cgen = new ClassGen(jc);
ConstantPoolGen cp = cgen.getConstantPool();
cgen.addAnnotation(createCombinedAnnotation(cp));
assertTrue("Should now have two annotations but has "+cgen.getAnnotations().length,
cgen.getAnnotations().length==2);
dumpClass(cgen,"SimpleAnnotatedClass.class");
JavaClass jc2 = getClassFrom(".","SimpleAnnotatedClass");
jc2.getAnnotations();
assertTrue(wipe("SimpleAnnotatedClass.class"));
// System.err.println(jc2.toString());
}
private void dumpClass(ClassGen cg, String fname) {
try {
File f = createTestdataFile(fname);
cg.getJavaClass().dump(f);
} catch (java.io.IOException e) {
System.err.println(e);
}
}

private void dumpClass(ClassGen cg, String dir, String fname) {
dumpClass(cg,dir+File.separator+fname);
}

private void buildClassContentsWithAnnotatedMethods(ClassGen cg, ConstantPoolGen cp, InstructionList il) {
// Create method 'public static void main(String[]argv)'
MethodGen mg = createMethodGen("main",il,cp);
InstructionFactory factory = new InstructionFactory(cg);
mg.addAnnotation(createSimpleVisibleAnnotation(mg.getConstantPool()));
// We now define some often used types:

ObjectType i_stream = new ObjectType("java.io.InputStream");
ObjectType p_stream = new ObjectType("java.io.PrintStream");

// Create variables in and name : We call the constructors, i.e.,
// execute BufferedReader(InputStreamReader(System.in)) . The reference
// to the BufferedReader object stays on top of the stack and is stored
// in the newly allocated in variable.

il.append(factory.createNew("java.io.BufferedReader"));
il.append(InstructionConstants.DUP); // Use predefined constant
il.append(factory.createNew("java.io.InputStreamReader"));
il.append(InstructionConstants.DUP);
il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,Constants.GETSTATIC));
il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
Constants.INVOKESPECIAL));

LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
"java.io.BufferedReader"), null, null);
int in = lg.getIndex();
lg.setStart(il.append(new ASTORE(in))); // "in" valid from here

// Create local variable name and initialize it to null

lg = mg.addLocalVariable("name", Type.STRING, null, null);
int name = lg.getIndex();
il.append(InstructionConstants.ACONST_NULL);
lg.setStart(il.append(new ASTORE(name))); // "name" valid from here

// Create try-catch block: We remember the start of the block, read a
// line from the standard input and store it into the variable name .

// InstructionHandle try_start = il.append(factory.createFieldAccess(
// "java.lang.System", "out", p_stream, Constants.GETSTATIC));

// il.append(new PUSH(cp, "Please enter your name> "));
// il.append(factory.createInvoke("java.io.PrintStream", "print",
// Type.VOID, new Type[] { Type.STRING },
// Constants.INVOKEVIRTUAL));
// il.append(new ALOAD(in));
// il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
// Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
InstructionHandle try_start = il.append(new PUSH(cp,"Andy"));
il.append(new ASTORE(name));

// Upon normal execution we jump behind exception handler, the target
// address is not known yet.

GOTO g = new GOTO(null);
InstructionHandle try_end = il.append(g);

// We add the exception handler which simply returns from the method.

LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
int var_ex_slot = var_ex.getIndex();
InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
var_ex.setStart(handler);
var_ex.setEnd(il.append(InstructionConstants.RETURN));
mg.addExceptionHandler(try_start, try_end, handler,
new ObjectType("java.io.IOException"));

// "Normal" code continues, now we can set the branch target of the GOTO
// .

InstructionHandle ih = il.append(factory.createFieldAccess(
"java.lang.System", "out", p_stream, Constants.GETSTATIC));
g.setTarget(ih);

// Printing "Hello": String concatenation compiles to StringBuffer
// operations.

il.append(factory.createNew(Type.STRINGBUFFER));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cp, "Hello, "));
il
.append(factory.createInvoke("java.lang.StringBuffer",
"<init>", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKESPECIAL));
il.append(new ALOAD(name));
il.append(factory.createInvoke("java.lang.StringBuffer", "append",
Type.STRINGBUFFER, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));

il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.RETURN);

// Finalization: Finally, we have to set the stack size, which normally
// would have to be computed on the fly and add a default constructor
// method to the class, which is empty in this case.

mg.setMaxStack();
mg.setMaxLocals();
cg.addMethod(mg.getMethod());
il.dispose(); // Allow instruction handles to be reused
cg.addEmptyConstructor(Constants.ACC_PUBLIC);
}
private void buildClassContents(ClassGen cg, ConstantPoolGen cp, InstructionList il) {
// Create method 'public static void main(String[]argv)'
MethodGen mg = createMethodGen("main",il,cp);
InstructionFactory factory = new InstructionFactory(cg);
// We now define some often used types:

ObjectType i_stream = new ObjectType("java.io.InputStream");
ObjectType p_stream = new ObjectType("java.io.PrintStream");

// Create variables in and name : We call the constructors, i.e.,
// execute BufferedReader(InputStreamReader(System.in)) . The reference
// to the BufferedReader object stays on top of the stack and is stored
// in the newly allocated in variable.

il.append(factory.createNew("java.io.BufferedReader"));
il.append(InstructionConstants.DUP); // Use predefined constant
il.append(factory.createNew("java.io.InputStreamReader"));
il.append(InstructionConstants.DUP);
il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,Constants.GETSTATIC));
il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
Constants.INVOKESPECIAL));

LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
"java.io.BufferedReader"), null, null);
int in = lg.getIndex();
lg.setStart(il.append(new ASTORE(in))); // "in" valid from here

// Create local variable name and initialize it to null

lg = mg.addLocalVariable("name", Type.STRING, null, null);
int name = lg.getIndex();
il.append(InstructionConstants.ACONST_NULL);
lg.setStart(il.append(new ASTORE(name))); // "name" valid from here

// Create try-catch block: We remember the start of the block, read a
// line from the standard input and store it into the variable name .

// InstructionHandle try_start = il.append(factory.createFieldAccess(
// "java.lang.System", "out", p_stream, Constants.GETSTATIC));

// il.append(new PUSH(cp, "Please enter your name> "));
// il.append(factory.createInvoke("java.io.PrintStream", "print",
// Type.VOID, new Type[] { Type.STRING },
// Constants.INVOKEVIRTUAL));
// il.append(new ALOAD(in));
// il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
// Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
InstructionHandle try_start = il.append(new PUSH(cp,"Andy"));
il.append(new ASTORE(name));

// Upon normal execution we jump behind exception handler, the target
// address is not known yet.

GOTO g = new GOTO(null);
InstructionHandle try_end = il.append(g);

// We add the exception handler which simply returns from the method.

LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
int var_ex_slot = var_ex.getIndex();
InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
var_ex.setStart(handler);
var_ex.setEnd(il.append(InstructionConstants.RETURN));
mg.addExceptionHandler(try_start, try_end, handler,
new ObjectType("java.io.IOException"));

// "Normal" code continues, now we can set the branch target of the GOTO
// .

InstructionHandle ih = il.append(factory.createFieldAccess(
"java.lang.System", "out", p_stream, Constants.GETSTATIC));
g.setTarget(ih);

// Printing "Hello": String concatenation compiles to StringBuffer
// operations.

il.append(factory.createNew(Type.STRINGBUFFER));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cp, "Hello, "));
il
.append(factory.createInvoke("java.lang.StringBuffer",
"<init>", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKESPECIAL));
il.append(new ALOAD(name));
il.append(factory.createInvoke("java.lang.StringBuffer", "append",
Type.STRINGBUFFER, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));

il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.RETURN);

// Finalization: Finally, we have to set the stack size, which normally
// would have to be computed on the fly and add a default constructor
// method to the class, which is empty in this case.

mg.setMaxStack();
mg.setMaxLocals();
cg.addMethod(mg.getMethod());
il.dispose(); // Allow instruction handles to be reused
cg.addEmptyConstructor(Constants.ACC_PUBLIC);
}

private JavaClass getClassFrom(String where,String clazzname) throws ClassNotFoundException {
SyntheticRepository repos = createRepos(where);
return repos.loadClass(clazzname);
}

// helper methods

private ClassGen createClassGen(String classname) {
return new ClassGen(classname, "java.lang.Object",
"<generated>", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
}
private MethodGen createMethodGen(String methodname,InstructionList il,ConstantPoolGen cp) {
return new MethodGen(
Constants.ACC_STATIC | Constants.ACC_PUBLIC, // access flags
Type.VOID, // return type
new Type[] { new ArrayType(Type.STRING, 1) }, // argument types
new String[] { "argv" }, // arg names
methodname, "HelloWorld", // method, class
il, cp);
}

public AnnotationGen createSimpleVisibleAnnotation(ConstantPoolGen cp) {
SimpleElementValueGen evg = new SimpleElementValueGen(
ElementValueGen.PRIMITIVE_INT, cp, 4);

ElementNameValuePairGen nvGen = new ElementNameValuePairGen("id", evg,cp);

ObjectType t = new ObjectType("SimpleAnnotation");

List elements = new ArrayList();
elements.add(nvGen);

AnnotationGen a = new AnnotationGen(t, elements,true, cp);
return a;
}
public AnnotationGen createFruitAnnotation(ConstantPoolGen cp,String aFruit) {
SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.STRING,cp,aFruit);
ElementNameValuePairGen nvGen = new ElementNameValuePairGen("fruit",evg,cp);
ObjectType t = new ObjectType("SimpleStringAnnotation");
List elements = new ArrayList();
elements.add(nvGen);
return new AnnotationGen(t,elements,true,cp);
}
public AnnotationGen createCombinedAnnotation(ConstantPoolGen cp) {
// Create an annotation instance
AnnotationGen a = createSimpleVisibleAnnotation(cp);
ArrayElementValueGen array = new ArrayElementValueGen(cp);
array.addElement(new AnnotationElementValueGen(a,cp));
ElementNameValuePairGen nvp = new ElementNameValuePairGen("value",array,cp);
List elements = new ArrayList();
elements.add(nvp);
return new AnnotationGen(new ObjectType("CombinedAnnotation"),elements,true,cp);
}
public AnnotationGen createSimpleInvisibleAnnotation(ConstantPoolGen cp) {
SimpleElementValueGen evg = new SimpleElementValueGen(
ElementValueGen.PRIMITIVE_INT, cp, 4);

ElementNameValuePairGen nvGen = new ElementNameValuePairGen("id", evg,cp);

ObjectType t = new ObjectType("SimpleAnnotation");

List elements = new ArrayList();
elements.add(nvGen);

AnnotationGen a = new AnnotationGen(t, elements,false, cp);
return a;
}
protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 72
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/LocalVariableTypeTableTest.java View File

@@ -0,0 +1,72 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import org.aspectj.apache.bcel.classfile.Code;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.LocalVariable;
import org.aspectj.apache.bcel.classfile.LocalVariableTypeTable;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.Utility;


public class LocalVariableTypeTableTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}
/**
* Check the local variable type table includes information about generic signatures.
*/
public void testLocalVariableTypeTableAttribute() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("SimpleGenericsProgram");
Method mainMethod = getMethod(clazz,"main");
Code codeAttr = (Code) findAttribute("Code",mainMethod.getAttributes());
LocalVariableTypeTable localVariableTypeTable =
(LocalVariableTypeTable) findAttribute("LocalVariableTypeTable",codeAttr.getAttributes());
assertTrue("Should be two entries in the LocalVariableTypeTable but found "+localVariableTypeTable.getTableLength(),
localVariableTypeTable.getTableLength()==2);

LocalVariable[] lvtable = localVariableTypeTable.getLocalVariableTypeTable();
boolean tc1OK = false;
boolean tc2OK = false;
String errormessage = null;
for (int i = 0; i < lvtable.length; i++) {
String sig = Utility.signatureToString(lvtable[i].getSignature());
if (lvtable[i].getName().equals("tc1")) {
if (!sig.equals("TreasureChest<String>")) {
errormessage="Expected signature of 'TreasureChest<String>' for tc1 but got "+sig;
} else {
tc1OK = true;
}
}
if (lvtable[i].getName().equals("tc2")) {
if (!sig.equals("TreasureChest<Integer>")) {
errormessage="Expected signature of 'TreasureChest<Integer>' for tc2 but got "+sig;
} else {
tc2OK = true;
}
}
}
if (!tc1OK || !tc2OK) fail(errormessage);
}
protected void tearDown() throws Exception {
super.tearDown();
}
}

+ 108
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/MethodAnnotationsTest.java View File

@@ -0,0 +1,108 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class MethodAnnotationsTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}
public void testMethodAnnotations() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("AnnotatedMethods");
checkAnnotatedMethod(clazz,"method1","SimpleAnnotation","id","1");
checkAnnotatedMethod(clazz,"method2","SimpleAnnotation","id","2");

}
public void testMethodAnnotationsReadWrite() throws ClassNotFoundException,IOException {
JavaClass clazz = getClassFromJar("AnnotatedMethods");
checkAnnotatedMethod(clazz,"method1","SimpleAnnotation","id","1");
checkAnnotatedMethod(clazz,"method2","SimpleAnnotation","id","2");
// Write it out
File tfile = createTestdataFile("AnnotatedMethods.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedMethods");
checkAnnotatedMethod(clazz,"method1","SimpleAnnotation","id","1");
checkAnnotatedMethod(clazz,"method2","SimpleAnnotation","id","2");

assertTrue(tfile.delete());
}
// helper methods
public void checkAnnotatedMethod(JavaClass clazz,String methodname,
String annotationName,String annotationElementName,String annotationElementValue) {
Method[] methods = clazz.getMethods();

for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
Annotation[] methodAnnotations = m.getAnnotations();
if (m.getName().equals(methodname)) {
checkAnnotation(methodAnnotations[0],annotationName,annotationElementName,annotationElementValue);
}
}
}
private void checkAnnotation(Annotation a,String name,String elementname,String elementvalue) {
assertTrue("Expected annotation to have name "+name+" but it had name "+a.getTypeName(),
a.getTypeName().equals(name));
assertTrue("Expected annotation to have one element but it had "+a.getValues().size(),a.getValues().size()==1);
ElementNameValuePair envp = (ElementNameValuePair)a.getValues().get(0);
assertTrue("Expected element name "+elementname+" but was "+envp.getNameString(),
elementname.equals(envp.getNameString()));
assertTrue("Expected element value "+elementvalue+" but was "+envp.getValue().stringifyValue(),
elementvalue.equals(envp.getValue().stringifyValue()));
}

// helper methods
public void checkValue(Annotation a,String name,String tostring) {
for (Iterator i = a.getValues().iterator(); i.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) i.next();
if (element.getNameString().equals(name)) {
if (!element.getValue().stringifyValue().equals(tostring)) {
fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
}
return;
}
}
fail("Didnt find named element "+name);
}

protected void tearDown() throws Exception {
super.tearDown();
}
}

+ 593
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/ParameterAnnotationsTest.java View File

@@ -0,0 +1,593 @@
/*******************************************************************************
* Copyright (c) 2004 IBM All rights reserved. This program and the accompanying
* materials are made available under the terms of the Common Public License
* v1.0 which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors: Andy Clement - initial implementation
******************************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.generic.ALOAD;
import org.aspectj.apache.bcel.generic.ASTORE;
import org.aspectj.apache.bcel.generic.ArrayType;
import org.aspectj.apache.bcel.generic.ClassGen;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.GOTO;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.LocalVariableGen;
import org.aspectj.apache.bcel.generic.MethodGen;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.PUSH;
import org.aspectj.apache.bcel.generic.Type;
import org.aspectj.apache.bcel.generic.annotation.AnnotationElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen;
import org.aspectj.apache.bcel.generic.annotation.ArrayElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.ElementNameValuePairGen;
import org.aspectj.apache.bcel.generic.annotation.ElementValueGen;
import org.aspectj.apache.bcel.generic.annotation.SimpleElementValueGen;
import org.aspectj.apache.bcel.util.SyntheticRepository;

/**
* The program that some of the tests generate looks like this:
public class HelloWorld {
public static void main(String[] argv) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String name = null;
try {
name = "Andy";
} catch(IOException e) { return; }
System.out.println("Hello, " + name);
}
}
*
*/
public class ParameterAnnotationsTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}

/**
* Programmatically construct a class and add an annotation to the main method parameter 'argv'
*/
public void testParameterAnnotations_builtOK() {
ClassGen clg = createClassGen("HelloWorld");
ConstantPoolGen cpg = clg.getConstantPool();
InstructionList il = new InstructionList();
buildClassContentsWithAnnotatedMethods(clg,cpg,il,true);
int i = clg.getMethods().length;
assertTrue("Class should have 2 methods but has "+i,i==2);
Method mainMethod = clg.getMethods()[0];
Annotation[] annos = mainMethod.getAnnotationsOnParameter(0);
assertTrue("Should be two annotation on the 'argv' parameter to main() but there are "+annos.length,annos.length==2);
assertTrue("This annotation should contain the string 'fruit=Apples' but it is "+annos[0].toString(),
annos[0].toString().indexOf("fruit=Apples")!=-1);
assertTrue("This annotation should contain the string 'fruit=Oranges' but it is "+annos[1].toString(),
annos[1].toString().indexOf("fruit=Oranges")!=-1);
}
/**
* Check we can save and load a constructed class that contains parameter annotations
*/
public void testParameterAnnotations_savedAndLoadedOK() throws ClassNotFoundException {
ClassGen clg = createClassGen("HelloWorld");
ConstantPoolGen cpg = clg.getConstantPool();
InstructionList il = new InstructionList();
buildClassContentsWithAnnotatedMethods(clg,cpg,il,true);
dumpClass(clg,"temp5","HelloWorld.class");
JavaClass jc = getClassFrom("temp5","HelloWorld");
clg = new ClassGen(jc);
int i = clg.getMethods().length;
assertTrue("Class should have 2 methods but has "+i,i==2);
Method mainMethod = clg.getMethods()[0];
Annotation[] annos = mainMethod.getAnnotationsOnParameter(0);
assertTrue("Should be two annotation on the 'argv' parameter to main() but there are "+annos.length,annos.length==2);
assertTrue("This annotation should contain the string 'fruit=Apples' but it is "+annos[0].toString(),
annos[0].toString().indexOf("fruit=Apples")!=-1);
assertTrue("This annotation should contain the string 'fruit=Oranges' but it is "+annos[1].toString(),
annos[1].toString().indexOf("fruit=Oranges")!=-1);
assertTrue(wipe("temp5","HelloWorld.class"));
}

/*
* Load an existing class, add new parameter annotations, save and then reload it
*/
public void testParameterAnnotations_loadedThenModifiedThenSavedAndLoadedOK() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","AnnotatedParameters");
ClassGen clg = new ClassGen(jc);
ConstantPoolGen cpg = clg.getConstantPool();
//
// Foo method looks like this:
// public void foo(@SimpleAnnotation(id=2) int arg1,
// @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
Method m = findMethod(clg,"foo");
assertTrue("Should be able to find method foo but couldn't",m!=null);
/////////////////////// 1. Check the right number of annotations are there
int i = m.getAnnotationsOnParameter(1).length;
assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
/////////////////////// 2. Let's add a new parameter annotation, a visible one, to the first parameter.

// Build a modifiable version of the foo method
MethodGen mg = new MethodGen(m,clg.getClassName(),cpg);
// Check the annotations survived that transform
i = mg.getAnnotationsOnParameter(1).size();
assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
// That worked, so let's add a new parameter annotation
mg.addParameterAnnotation(0,createFruitAnnotation(cpg,"Banana",true));
// Foo method should now look like this:
// public void foo(@SimpleAnnotation(id=2) @SimpleStringAnnotation(fruit=Banana) int arg1,
// @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
i = mg.getAnnotationsOnParameter(0).size();
assertTrue("Should now be 2 parameter annotations but found "+i,i==2);
i = mg.getAnnotationsOnParameter(0).get(1).toString().indexOf("fruit=Banana");
assertTrue("Expected 'fruit=Banana' in the 2nd annotation on the first argument but got "+
mg.getAnnotationsOnParameter(0).get(1).toString(),i!=-1);

// delete the old method and add the new one
clg.removeMethod(m);
clg.addMethod(mg.getMethod());
/////////////////////// 3. Dump it to disk
dumpClass(clg,"temp2","AnnotatedParameters.class");
/////////////////////// 4. Load it back in and verify the annotations persisted
JavaClass jc2 = getClassFrom("temp2","AnnotatedParameters");

m = jc2.getMethods()[2];
Annotation[] p1annotations = m.getAnnotationsOnParameter(0);
Annotation[] p2annotations = m.getAnnotationsOnParameter(1);
assertTrue("Expected two annotations on the first parameter but found "+p1annotations.length,p1annotations.length==2);
assertTrue("Expected two annotations on the second parameter but found "+p2annotations.length,p2annotations.length==2);
String expectedString = "[@SimpleAnnotation(id=2),@SimpleStringAnnotation(fruit=Banana)]";
assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p1annotations)+"'",
dumpAnnotations(p1annotations).equals(expectedString));
expectedString = "[@SimpleAnnotation(id=3),@AnnotationEnumElement(enumval=Red)]";
assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p2annotations)+"'",
dumpAnnotations(p2annotations).equals(expectedString));
assertTrue(wipe("temp2","AnnotatedParameters.class"));
}
/**
* same as above test but attaching invisible runtime parameter annotations
*/
public void testParameterAnnotations_loadedThenModifiedWithInvisibleAnnotationThenSavedAndLoadedOK() throws ClassNotFoundException {
JavaClass jc = getClassFrom("testcode.jar","AnnotatedParameters");
ClassGen clg = new ClassGen(jc);
ConstantPoolGen cpg = clg.getConstantPool();
//
// Foo method looks like this:
// public void foo(@SimpleAnnotation(id=2) int arg1,
// @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
Method m = findMethod(clg,"foo");
assertTrue("Should be able to find method foo but couldn't",m!=null);
/////////////////////// 1. Check the right number of annotations are there
int i = m.getAnnotationsOnParameter(1).length;
assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
/////////////////////// 2. Let's add a new parameter annotation, a visible one, to the first parameter.

// Build a modifiable version of the foo method
MethodGen mg = new MethodGen(m,clg.getClassName(),cpg);
// Check the annotations survived that transform
i = mg.getAnnotationsOnParameter(1).size();
assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
// That worked, so let's add a new parameter annotation
mg.addParameterAnnotation(0,createFruitAnnotation(cpg,"Banana",false));
// Foo method should now look like this:
// public void foo(@SimpleAnnotation(id=2) @SimpleStringAnnotation(fruit=Banana) int arg1,
// @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
i = mg.getAnnotationsOnParameter(0).size();
assertTrue("Should now be 2 parameter annotations but found "+i,i==2);
i = mg.getAnnotationsOnParameter(0).get(1).toString().indexOf("fruit=Banana");
assertTrue("Expected 'fruit=Banana' in the 2nd annotation on the first argument but got "+
mg.getAnnotationsOnParameter(0).get(1).toString(),i!=-1);
assertTrue("New annotation should be runtime invisible?",!((AnnotationGen)mg.getAnnotationsOnParameter(0).get(1)).isRuntimeVisible());

// delete the old method and add the new one
clg.removeMethod(m);
clg.addMethod(mg.getMethod());
/////////////////////// 3. Dump it to disk
dumpClass(clg,"temp3","AnnotatedParameters.class");
/////////////////////// 4. Load it back in and verify the annotations persisted

JavaClass jc2 = getClassFrom("temp3","AnnotatedParameters");

m = jc2.getMethods()[2];
Annotation[] p1annotations = m.getAnnotationsOnParameter(0);
Annotation[] p2annotations = m.getAnnotationsOnParameter(1);
assertTrue("Expected two annotations on the first parameter but found "+p1annotations.length,p1annotations.length==2);
assertTrue("Expected two annotations on the second parameter but found "+p2annotations.length,p2annotations.length==2);
String expectedString = "[@SimpleAnnotation(id=2),@SimpleStringAnnotation(fruit=Banana)]";
assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p1annotations)+"'",
dumpAnnotations(p1annotations).equals(expectedString));
expectedString = "[@SimpleAnnotation(id=3),@AnnotationEnumElement(enumval=Red)]";
assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p2annotations)+"'",
dumpAnnotations(p2annotations).equals(expectedString));
assertTrue("Second annotation on first parameter should be runtime invisible?",
!p1annotations[1].isRuntimeVisible());
assertTrue(wipe("temp3","AnnotatedParameters.class"));
// 5. Verify that when annotations for parameters are unpacked from attributes, the
// attributes vanish !
clg = new ClassGen(jc2);
mg = new MethodGen(m,clg.getClassName(),clg.getConstantPool());
Attribute[] as = mg.getAttributes();
assertTrue("Should be 2 (RIPA and RVPA) but there are "+mg.getAttributes().length,mg.getAttributes().length==2);
List l = mg.getAnnotationsOnParameter(0);
assertTrue("Should be 2 annotations on first parameter but there is only "+l.size()+":"+l.toString(),
l.size()==2);
assertTrue("Should be 0 but there are "+mg.getAttributes().length,mg.getAttributes().length==0);
}

private Method findMethod(ClassGen c,String mname) {
Method[] ms = c.getMethods();
for (int i = 0; i < ms.length; i++) {
if (ms[i].getName().equals(mname)) return ms[i];
}
return null;
}
private void dumpClass(ClassGen cg, String fname) {
try {
File f = createTestdataFile(fname);
cg.getJavaClass().dump(f);
} catch (java.io.IOException e) {
System.err.println(e);
}
}

private void dumpClass(ClassGen cg, String dir, String fname) {
dumpClass(cg,dir+File.separator+fname);
}

private void buildClassContentsWithAnnotatedMethods(ClassGen cg, ConstantPoolGen cp, InstructionList il,boolean addParameterAnnotations) {
// Create method 'public static void main(String[]argv)'
MethodGen mg = createMethodGen("main",il,cp);
InstructionFactory factory = new InstructionFactory(cg);
mg.addAnnotation(createSimpleVisibleAnnotation(mg.getConstantPool()));
// We now define some often used types:

ObjectType i_stream = new ObjectType("java.io.InputStream");
ObjectType p_stream = new ObjectType("java.io.PrintStream");

// Create variables in and name : We call the constructors, i.e.,
// execute BufferedReader(InputStreamReader(System.in)) . The reference
// to the BufferedReader object stays on top of the stack and is stored
// in the newly allocated in variable.

il.append(factory.createNew("java.io.BufferedReader"));
il.append(InstructionConstants.DUP); // Use predefined constant
il.append(factory.createNew("java.io.InputStreamReader"));
il.append(InstructionConstants.DUP);
il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,Constants.GETSTATIC));
il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
Constants.INVOKESPECIAL));

LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
"java.io.BufferedReader"), null, null);
int in = lg.getIndex();
lg.setStart(il.append(new ASTORE(in))); // "in" valid from here

// Create local variable name and initialize it to null

lg = mg.addLocalVariable("name", Type.STRING, null, null);
int name = lg.getIndex();
il.append(InstructionConstants.ACONST_NULL);
lg.setStart(il.append(new ASTORE(name))); // "name" valid from here

// Create try-catch block: We remember the start of the block, read a
// line from the standard input and store it into the variable name .

// InstructionHandle try_start = il.append(factory.createFieldAccess(
// "java.lang.System", "out", p_stream, Constants.GETSTATIC));

// il.append(new PUSH(cp, "Please enter your name> "));
// il.append(factory.createInvoke("java.io.PrintStream", "print",
// Type.VOID, new Type[] { Type.STRING },
// Constants.INVOKEVIRTUAL));
// il.append(new ALOAD(in));
// il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
// Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
InstructionHandle try_start = il.append(new PUSH(cp,"Andy"));
il.append(new ASTORE(name));

// Upon normal execution we jump behind exception handler, the target
// address is not known yet.

GOTO g = new GOTO(null);
InstructionHandle try_end = il.append(g);

// We add the exception handler which simply returns from the method.

LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
int var_ex_slot = var_ex.getIndex();
InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
var_ex.setStart(handler);
var_ex.setEnd(il.append(InstructionConstants.RETURN));
mg.addExceptionHandler(try_start, try_end, handler,
new ObjectType("java.io.IOException"));

// "Normal" code continues, now we can set the branch target of the GOTO
// .

InstructionHandle ih = il.append(factory.createFieldAccess(
"java.lang.System", "out", p_stream, Constants.GETSTATIC));
g.setTarget(ih);

// Printing "Hello": String concatenation compiles to StringBuffer
// operations.

il.append(factory.createNew(Type.STRINGBUFFER));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cp, "Hello, "));
il
.append(factory.createInvoke("java.lang.StringBuffer",
"<init>", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKESPECIAL));
il.append(new ALOAD(name));
il.append(factory.createInvoke("java.lang.StringBuffer", "append",
Type.STRINGBUFFER, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));

il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.RETURN);

// Finalization: Finally, we have to set the stack size, which normally
// would have to be computed on the fly and add a default constructor
// method to the class, which is empty in this case.

mg.addParameterAnnotation(0,createFruitAnnotation(cp,"Apples",true));
mg.addParameterAnnotation(0,createFruitAnnotation(cp,"Oranges",true));
mg.setMaxStack();
mg.setMaxLocals();
cg.addMethod(mg.getMethod());
il.dispose(); // Allow instruction handles to be reused
cg.addEmptyConstructor(Constants.ACC_PUBLIC);
}
private void buildClassContents(ClassGen cg, ConstantPoolGen cp, InstructionList il) {
// Create method 'public static void main(String[]argv)'
MethodGen mg = createMethodGen("main",il,cp);
InstructionFactory factory = new InstructionFactory(cg);
// We now define some often used types:

ObjectType i_stream = new ObjectType("java.io.InputStream");
ObjectType p_stream = new ObjectType("java.io.PrintStream");

// Create variables in and name : We call the constructors, i.e.,
// execute BufferedReader(InputStreamReader(System.in)) . The reference
// to the BufferedReader object stays on top of the stack and is stored
// in the newly allocated in variable.

il.append(factory.createNew("java.io.BufferedReader"));
il.append(InstructionConstants.DUP); // Use predefined constant
il.append(factory.createNew("java.io.InputStreamReader"));
il.append(InstructionConstants.DUP);
il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,Constants.GETSTATIC));
il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
Constants.INVOKESPECIAL));

LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
"java.io.BufferedReader"), null, null);
int in = lg.getIndex();
lg.setStart(il.append(new ASTORE(in))); // "in" valid from here

// Create local variable name and initialize it to null

lg = mg.addLocalVariable("name", Type.STRING, null, null);
int name = lg.getIndex();
il.append(InstructionConstants.ACONST_NULL);
lg.setStart(il.append(new ASTORE(name))); // "name" valid from here

// Create try-catch block: We remember the start of the block, read a
// line from the standard input and store it into the variable name .

// InstructionHandle try_start = il.append(factory.createFieldAccess(
// "java.lang.System", "out", p_stream, Constants.GETSTATIC));

// il.append(new PUSH(cp, "Please enter your name> "));
// il.append(factory.createInvoke("java.io.PrintStream", "print",
// Type.VOID, new Type[] { Type.STRING },
// Constants.INVOKEVIRTUAL));
// il.append(new ALOAD(in));
// il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
// Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
InstructionHandle try_start = il.append(new PUSH(cp,"Andy"));
il.append(new ASTORE(name));

// Upon normal execution we jump behind exception handler, the target
// address is not known yet.

GOTO g = new GOTO(null);
InstructionHandle try_end = il.append(g);

// We add the exception handler which simply returns from the method.

LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
int var_ex_slot = var_ex.getIndex();
InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
var_ex.setStart(handler);
var_ex.setEnd(il.append(InstructionConstants.RETURN));
mg.addExceptionHandler(try_start, try_end, handler,
new ObjectType("java.io.IOException"));

// "Normal" code continues, now we can set the branch target of the GOTO
// .

InstructionHandle ih = il.append(factory.createFieldAccess(
"java.lang.System", "out", p_stream, Constants.GETSTATIC));
g.setTarget(ih);

// Printing "Hello": String concatenation compiles to StringBuffer
// operations.

il.append(factory.createNew(Type.STRINGBUFFER));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cp, "Hello, "));
il
.append(factory.createInvoke("java.lang.StringBuffer",
"<init>", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKESPECIAL));
il.append(new ALOAD(name));
il.append(factory.createInvoke("java.lang.StringBuffer", "append",
Type.STRINGBUFFER, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));

il.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.RETURN);

// Finalization: Finally, we have to set the stack size, which normally
// would have to be computed on the fly and add a default constructor
// method to the class, which is empty in this case.

mg.setMaxStack();
mg.setMaxLocals();
cg.addMethod(mg.getMethod());
il.dispose(); // Allow instruction handles to be reused
cg.addEmptyConstructor(Constants.ACC_PUBLIC);
}

private JavaClass getClassFrom(String where,String clazzname) throws ClassNotFoundException {
SyntheticRepository repos = createRepos(where);
return repos.loadClass(clazzname);
}

// helper methods

private ClassGen createClassGen(String classname) {
return new ClassGen(classname, "java.lang.Object",
"<generated>", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
}
private MethodGen createMethodGen(String methodname,InstructionList il,ConstantPoolGen cp) {
return new MethodGen(
Constants.ACC_STATIC | Constants.ACC_PUBLIC, // access flags
Type.VOID, // return type
new Type[] { new ArrayType(Type.STRING, 1) }, // argument types
new String[] { "argv" }, // arg names
methodname, "HelloWorld", // method, class
il, cp);
}

public AnnotationGen createSimpleVisibleAnnotation(ConstantPoolGen cp) {
SimpleElementValueGen evg = new SimpleElementValueGen(
ElementValueGen.PRIMITIVE_INT, cp, 4);

ElementNameValuePairGen nvGen = new ElementNameValuePairGen("id", evg,cp);

ObjectType t = new ObjectType("SimpleAnnotation");

List elements = new ArrayList();
elements.add(nvGen);

AnnotationGen a = new AnnotationGen(t, elements,true, cp);
return a;
}
public AnnotationGen createCombinedAnnotation(ConstantPoolGen cp) {
// Create an annotation instance
AnnotationGen a = createSimpleVisibleAnnotation(cp);
ArrayElementValueGen array = new ArrayElementValueGen(cp);
array.addElement(new AnnotationElementValueGen(a,cp));
ElementNameValuePairGen nvp = new ElementNameValuePairGen("value",array,cp);
List elements = new ArrayList();
elements.add(nvp);
return new AnnotationGen(new ObjectType("CombinedAnnotation"),elements,true,cp);
}
public AnnotationGen createSimpleInvisibleAnnotation(ConstantPoolGen cp) {
SimpleElementValueGen evg = new SimpleElementValueGen(
ElementValueGen.PRIMITIVE_INT, cp, 4);

ElementNameValuePairGen nvGen = new ElementNameValuePairGen("id", evg,cp);

ObjectType t = new ObjectType("SimpleAnnotation");

List elements = new ArrayList();
elements.add(nvGen);

AnnotationGen a = new AnnotationGen(t, elements,false, cp);
return a;
}
protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 373
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/RuntimeVisibleAnnotationAttributeTest.java View File

@@ -0,0 +1,373 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Utility;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class RuntimeVisibleAnnotationAttributeTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}
public void testSeeAnnotationsAsAttribute() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
ConstantPool pool = clazz.getConstantPool();
Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
assertTrue("Expected a RuntimeVisibleAnnotations attribute but found none",
rvaAttr.length==1);
}
public void testAnnotationsAttributeContainsRightData() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
ConstantPool pool = clazz.getConstantPool();
Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) rvaAttr[0];
List anns = rva.getAnnotations();
assertTrue("Should be one annotation but found "+anns.size(),
anns.size()==1);
Annotation ann = (Annotation) anns.get(0);
assertTrue("Should be called 'SimpleAnnotation' but was called "+ann.getTypeName(),
ann.getTypeName().equals("SimpleAnnotation"));
List l = ann.getValues();
assertTrue("Should be one value for annotation 'SimpleAnnotation' but found "+l.size(),
l.size()==1);
ElementNameValuePair envp = (ElementNameValuePair)l.get(0);
assertTrue("Name of element in SimpleAnnotation should be 'id' but it is "+envp.getNameString(),
envp.getNameString().equals("id"));
SimpleElementValue evalue = (SimpleElementValue)envp.getValue();
assertTrue("'id' should be of type int, but it is "+evalue.getElementValueType(),evalue.getElementValueType()==SimpleElementValue.PRIMITIVE_INT);
assertTrue("'id' should have value 4 but it is "+evalue.getValueInt(),
evalue.getValueInt()==4);
}
public void testAccessingAnnotationsOnClazz() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
ConstantPool pool = clazz.getConstantPool();
Annotation[] anns = clazz.getAnnotations();
assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
anns.length==1);
}
public void testReadingWritingAnnotations() throws ClassNotFoundException, IOException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
ConstantPool pool = clazz.getConstantPool();
Annotation[] anns = clazz.getAnnotations();
assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
anns.length==1);
// Write it out
File tfile = createTestdataFile("SimpleAnnotatedClass.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos.loadClass("SimpleAnnotatedClass");
ConstantPool pool2 = clazz2.getConstantPool();
Annotation[] anns2 = clazz2.getAnnotations();
assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns2.length,
anns2.length==1);
assertTrue(tfile.delete());
}
////
// Test for annotations containing string elements
public void testAnnotationStringElement() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedClass");
verifyAnnotationStringElement(clazz);
}

public void testAnnotationStringElementReadWrite() throws ClassNotFoundException, IOException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedClass");
verifyAnnotationStringElement(clazz);
// Write it out
File tfile = createTestdataFile("AnnotatedClass.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedClass");
verifyAnnotationStringElement(clazz2);

assertTrue(tfile.delete());
}

private void verifyAnnotationStringElement(JavaClass clazz) {
Annotation[] anns = clazz.getAnnotations();
assertTrue("should be one annotation but found "+anns.length,anns.length==1);
Annotation ann = anns[0];
assertTrue("should be called 'AnnotationStringElement' but was called "+ann.getTypeName(),
ann.getTypeName().equals("AnnotationStringElement"));
List l = ann.getValues();
assertTrue("Should be one value but there were "+l.size(),l.size()==1);
ElementNameValuePair nvp = (ElementNameValuePair)l.get(0);
assertTrue("Name of element should be 'stringval' but was "+nvp.getNameString(),
nvp.getNameString().equals("stringval"));
SimpleElementValue ev = (SimpleElementValue)nvp.getValue();
assertTrue("String value should be 'hello' but was '"+ev.getValueString()+"'",
ev.getValueString().equals("hello"));
}
////
// Test for complex annotation that includes all primitives
public void testComplexAnnotation() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
verifyComplexAnnotation(clazz);
}

public void testComplexAnnotationsReadWrite() throws ClassNotFoundException, IOException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
verifyComplexAnnotation(clazz);

// Write it out
File tfile = createTestdataFile("ComplexAnnotatedClass.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos.loadClass("ComplexAnnotatedClass");
verifyComplexAnnotation(clazz2);
assertTrue(tfile.delete());
}
private void verifyComplexAnnotation(JavaClass clazz) {
Annotation[] anns = clazz.getAnnotations();
assertTrue("Should be one annotation but found "+anns.length,anns.length==1);
Annotation ann = anns[0];
assertTrue("Should be called 'ComplexAnnotation' but was called "+ann.getTypeName(),
ann.getTypeName().equals("ComplexAnnotation"));
List l = ann.getValues();
assertTrue("Should be eight values for annotation 'ComplexAnnotation' but found "+l.size(),
l.size()==8);
List names = Utility.getListOfAnnotationNames(ann);
assertTrue("Cant find expected element ",names.contains("ival"));
assertTrue("Cant find expected element ",names.contains("dval"));
assertTrue("Cant find expected element ",names.contains("zval"));
assertTrue("Cant find expected element ",names.contains("fval"));
assertTrue("Cant find expected element ",names.contains("jval"));
assertTrue("Cant find expected element ",names.contains("sval"));
assertTrue("Cant find expected element ",names.contains("bval"));
assertTrue("Cant find expected element ",names.contains("cval"));
checkValue(ann,"ival","4");
checkValue(ann,"jval","56");
checkValue(ann,"fval","3.0");
checkValue(ann,"dval","33.4");
checkValue(ann,"sval","99");
checkValue(ann,"bval","2");
checkValue(ann,"cval","5");
checkValue(ann,"zval","false");
}

private void checkValue(Annotation a,String name,String tostring) {
for (Iterator i = a.getValues().iterator(); i.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) i.next();
if (element.getNameString().equals(name)) {
if (!element.getValue().stringifyValue().equals(tostring)) {
fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
}
return;
}
}
fail("Didnt find named element "+name);
}

////
// Test an annotation containing a 'Class' element
public void testAnnotationClassElement() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
verifyClassAnnotation(clazz);
}
public void testAnnotationClassElementReadWrite() throws ClassNotFoundException,IOException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
verifyClassAnnotation(clazz);

// Write it out
File tfile = createTestdataFile("AnnotatedWithClassClass.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedWithClassClass");
verifyClassAnnotation(clazz2);
assertTrue(wipe("AnnotatedWithClassClass.class"));
}
private void verifyClassAnnotation(JavaClass clazz) {
Annotation[] anns = clazz.getAnnotations();
assertTrue("should be one annotation but found "+anns.length,anns.length==1);
Annotation ann = anns[0];
assertTrue("should be called 'AnnotationClassElement' but was called "+ann.getTypeName(),
ann.getTypeName().equals("AnnotationClassElement"));
List l = ann.getValues();
assertTrue("Should be one value but there were "+l.size(),l.size()==1);
ElementNameValuePair nvp = (ElementNameValuePair)l.get(0);
assertTrue("Name of element should be 'clz' but was "+nvp.getNameString(),
nvp.getNameString().equals("clz"));
ClassElementValue ev = (ClassElementValue)nvp.getValue();
assertTrue("String value should be 'Ljava/lang/Integer;' but was '"+ev.getClassString()+"'",
ev.getClassString().equals("Ljava/lang/Integer;"));
}
////
// Test an annotation containing an enum element
public void testAnnotationEnumElement() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
verifyAnnotationEnumElement(clazz);
}
public void testAnnotationEnumElementReadWrite() throws ClassNotFoundException, IOException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
verifyAnnotationEnumElement(clazz);

// Write it out
File tfile = createTestdataFile("AnnotatedWithEnumClass.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedWithEnumClass");
verifyAnnotationEnumElement(clazz2);
assertTrue(tfile.delete());
}
public void verifyAnnotationEnumElement(JavaClass clazz) {
Annotation[] anns = clazz.getAnnotations();
assertTrue("should be one annotation but found "+anns.length,anns.length==1);
Annotation ann = anns[0];
assertTrue("should be called 'AnnotationEnumElement' but was called "+ann.getTypeName(),
ann.getTypeName().equals("AnnotationEnumElement"));
List l = ann.getValues();
assertTrue("Should be one value but there were "+l.size(),l.size()==1);
ElementNameValuePair nvp = (ElementNameValuePair)l.get(0);
assertTrue("Name of element should be 'enumval' but was "+nvp.getNameString(),
nvp.getNameString().equals("enumval"));
ElementValue ev = nvp.getValue();
assertTrue("Should be of type EnumElementValue but is "+ev,ev instanceof EnumElementValue);
EnumElementValue eev = (EnumElementValue)ev;
assertTrue("Should be an enum type value but is "+eev.getElementValueType(),eev.getElementValueType()==SimpleElementValue.ENUM_CONSTANT);
assertTrue("Enum type for annotation should be 'SimpleEnum' but is "+eev.getEnumTypeString(),eev.getEnumTypeString().equals("SimpleEnum"));
assertTrue("String value should be 'Red' but was '"+eev.getEnumValueString()+"'",
eev.getEnumValueString().equals("Red"));
}
////
// Test an annotation with an array element
public void testAnnotationArraysOfAnnotations() throws ClassNotFoundException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
Annotation[] anns = clazz.getAnnotations();
assertTrue("should be one annotation but found "+anns.length,anns.length==1);
checkCombinedAnnotation(anns[0]);
}
public void testAnnotationArraysOfAnnotationsReadWrite() throws ClassNotFoundException, IOException {
SyntheticRepository repos = createRepos("testcode.jar");
JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
Annotation[] anns = clazz.getAnnotations();
assertTrue("should be one annotation but found "+anns.length,anns.length==1);
checkCombinedAnnotation(anns[0]);
// Write it out
File tfile = createTestdataFile("AnnotatedWithCombinedAnnotation.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedWithCombinedAnnotation");
Annotation[] anns2 = clazz2.getAnnotations();
assertTrue("should be one annotation but found "+anns2.length,anns2.length==1);
checkCombinedAnnotation(anns2[0]);

assertTrue(tfile.delete());
}
private void checkCombinedAnnotation(Annotation ann) {
assertTrue("should be called 'CombinedAnnotation' but was called "+ann.getTypeName(),
ann.getTypeName().equals("CombinedAnnotation"));
List l = ann.getValues();
assertTrue("Should be one value but there were "+l.size(),l.size()==1);
ElementNameValuePair nvp = (ElementNameValuePair)l.get(0);
assertTrue("Name of element should be 'value' but was "+nvp.getNameString(),
nvp.getNameString().equals("value"));
ElementValue ev = nvp.getValue();
assertTrue("Should be of type ArrayElementValue but is "+ev,ev instanceof ArrayElementValue);
ArrayElementValue aev = (ArrayElementValue)ev;
assertTrue("Array element value should be of size 1 but is "+aev.getElementValuesArraySize(),
aev.getElementValuesArraySize()==1);
ElementValue[] evs = aev.getElementValuesArray();
assertTrue("Entry in the array should be AnnotationElementValue but is "+evs[0],
evs[0] instanceof AnnotationElementValue);
AnnotationElementValue inner_ev = (AnnotationElementValue)evs[0];
Annotation a = inner_ev.getAnnotation();
assertTrue("Should be SimpleAnnotation but is "+a.getTypeName(),a.getTypeName().equals("SimpleAnnotation"));
List envps = a.getValues();
assertTrue("Should be one name value pair but found "+envps.size(),envps.size()==1);
ElementNameValuePair envp = (ElementNameValuePair) envps.get(0);
assertTrue("Name should be 'id' but it is "+envp.getNameString(),envp.getNameString().equals("id"));
assertTrue("Value of 'id' should be 4 but it is "+envp.getValue().stringifyValue(),
envp.getValue().stringifyValue().equals("4"));
}

protected void tearDown() throws Exception {
super.tearDown();
}
}

+ 143
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/RuntimeVisibleParameterAnnotationAttributeTest.java View File

@@ -0,0 +1,143 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleParameterAnnotations;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class RuntimeVisibleParameterAnnotationAttributeTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}

public void testAccessingRuntimeVisibleParameterAnnotations() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("AnnotatedParameters");
Attribute[] rvaAttr = findAttribute("RuntimeVisibleParameterAnnotations",clazz);
Method[] methods = clazz.getMethods();

for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName().equals("foo")) {
RuntimeVisibleParameterAnnotations paramAnns =
(RuntimeVisibleParameterAnnotations) findAttribute("RuntimeVisibleParameterAnnotations",m.getAttributes());
assertTrue("foo takes two parameters, not "+paramAnns.getParameterAnnotations().size(),
paramAnns.getParameterAnnotations().size()==2);

Annotation[] firstParamAnnotations = paramAnns.getAnnotationsOnParameter(0);
checkAnnotation(firstParamAnnotations[0],"SimpleAnnotation","id","2");

Annotation[] secondParamAnnotations = paramAnns.getAnnotationsOnParameter(1);
checkAnnotation(secondParamAnnotations[0],"SimpleAnnotation","id","3");
checkAnnotation(secondParamAnnotations[1],"AnnotationEnumElement","enumval","Red");
}
if (m.getName().equals("main")) {
RuntimeVisibleParameterAnnotations paramAnns =
(RuntimeVisibleParameterAnnotations) findAttribute("RuntimeVisibleParameterAnnotations",m.getAttributes());
assertTrue("main takes one parameter, not "+paramAnns.getParameterAnnotations().size(),
paramAnns.getParameterAnnotations().size()==1);

Annotation[] firstParamAnnotations = paramAnns.getAnnotationsOnParameter(0);
checkAnnotation(firstParamAnnotations[0],"SimpleAnnotation","id","1");
}
}
}
public void testAccessingParameterAnnotationsThroughGetAnnotations() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("AnnotatedParameters");
Attribute[] rvaAttr = findAttribute("RuntimeVisibleParameterAnnotations",clazz);
checkFooMethod(clazz);
}
public void testParameterAnnotationsReadWrite() throws ClassNotFoundException,IOException {
JavaClass clazz = getClassFromJar("AnnotatedParameters");
checkFooMethod(clazz);

// Write it out
File tfile = createTestdataFile("AnnotatedParameters.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("AnnotatedParameters");
checkFooMethod(clazz);

assertTrue(tfile.delete());
}
public void checkFooMethod(JavaClass clazz) {
Method[] methods = clazz.getMethods();

for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName().equals("foo")) {

Annotation[] firstParamAnnotations = m.getAnnotationsOnParameter(0);
checkAnnotation(firstParamAnnotations[0],"SimpleAnnotation","id","2");

Annotation[] secondParamAnnotations = m.getAnnotationsOnParameter(1);
checkAnnotation(secondParamAnnotations[0],"SimpleAnnotation","id","3");
checkAnnotation(secondParamAnnotations[1],"AnnotationEnumElement","enumval","Red");
}
}
}
private void checkAnnotation(Annotation a,String name,String elementname,String elementvalue) {
assertTrue("Expected annotation to have name "+name+" but it had name "+a.getTypeName(),
a.getTypeName().equals(name));
assertTrue("Expected annotation to have one element but it had "+a.getValues().size(),a.getValues().size()==1);
ElementNameValuePair envp = (ElementNameValuePair)a.getValues().get(0);
assertTrue("Expected element name "+elementname+" but was "+envp.getNameString(),
elementname.equals(envp.getNameString()));
assertTrue("Expected element value "+elementvalue+" but was "+envp.getValue().stringifyValue(),
elementvalue.equals(envp.getValue().stringifyValue()));
}

// helper methods
public void checkValue(Annotation a,String name,String tostring) {
for (Iterator i = a.getValues().iterator(); i.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) i.next();
if (element.getNameString().equals(name)) {
if (!element.getValue().stringifyValue().equals(tostring)) {
fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
}
return;
}
}
fail("Didnt find named element "+name);
}

protected void tearDown() throws Exception {
super.tearDown();
}
}

+ 97
- 0
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/VarargsTest.java View File

@@ -0,0 +1,97 @@
/* *******************************************************************
* Copyright (c) 2004 IBM
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Andy Clement - initial implementation
* ******************************************************************/

package org.aspectj.apache.bcel.classfile.tests;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePair;
import org.aspectj.apache.bcel.util.SyntheticRepository;


public class VarargsTest extends BcelTestCase {

protected void setUp() throws Exception {
super.setUp();
}
public void testVarargs() throws ClassNotFoundException {
JavaClass clazz = getClassFromJar("VarargsClass");
checkMarkedVarargs(clazz,"foo",true);
checkMarkedVarargs(clazz,"goo",true);
checkMarkedVarargs(clazz,"hoo",false);
}
public void testVarargsReadWrite() throws ClassNotFoundException,IOException {
JavaClass clazz = getClassFromJar("VarargsClass");
checkMarkedVarargs(clazz,"foo",true);
checkMarkedVarargs(clazz,"goo",true);
checkMarkedVarargs(clazz,"hoo",false);
// Write it out
File tfile = createTestdataFile("VarargsClass.class");
clazz.dump(tfile);
SyntheticRepository repos2 = createRepos(".");
JavaClass clazz2 = repos2.loadClass("VarargsClass");
checkMarkedVarargs(clazz,"foo",true);
checkMarkedVarargs(clazz,"goo",true);
checkMarkedVarargs(clazz,"hoo",false);

assertTrue(tfile.delete());
}
// helper methods
public void checkMarkedVarargs(JavaClass clazz,String methodname,boolean shouldBeMarked) {
Method[] methods = clazz.getMethods();

for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName().equals(methodname)) {
assertTrue("Method '"+methodname+"' should answer varargs="+shouldBeMarked,
m.isVarargs()==shouldBeMarked);
}
}
}

// helper methods
public void checkValue(Annotation a,String name,String tostring) {
for (Iterator i = a.getValues().iterator(); i.hasNext();) {
ElementNameValuePair element = (ElementNameValuePair) i.next();
if (element.getNameString().equals(name)) {
if (!element.getValue().stringifyValue().equals(tostring)) {
fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
}
return;
}
}
fail("Didnt find named element "+name);
}

protected void tearDown() throws Exception {
super.tearDown();
}
}

Loading…
Cancel
Save