Skip to content

Commit

Permalink
JANDEX-46 Add support for default annotation attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
n1hility committed Jul 31, 2018
1 parent d4dcdbd commit c208ff5
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 70 deletions.
101 changes: 101 additions & 0 deletions src/main/java/org/jboss/jandex/AnnotationInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.jboss.jandex;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -158,6 +159,106 @@ public AnnotationValue value() {
return value("value");
}


/**
* Returns a value that corresponds with the specified parameter name,
* accounting for its default value. Since an annotation's defaults are
* only stored on the annotation's defining class, and not usages of the
* annotation, an index containing the Annotation class must be provided
* as a parameter. If the index does not contain the defining annotation
* class, then an <code>IllegalArgumentException</code> will be thrown to
* prevent non-deterministic results.
*
* <p>
* If the parameter was not specified by this instance, then the
* annotation's <code>ClassInfo</code> is checked for a default value.
* If there is a default, that value is returned. Otherwise null is
* returned.
* </p>
*
* @param index the index containing the defining annotation class
* @param name the name of the annotation parameter
* @return the value of the specified parameter, the default, or null
* @throws IllegalArgumentException if index does not contain the defining
* annotation class
*/
public AnnotationValue valueWithDefault(IndexView index, String name) {
ClassInfo definition = index.getClassByName(this.name);
if (definition == null) {
throw new IllegalArgumentException("Index did not contain annotation definition: " + this.name);
}

AnnotationValue result = value(name);
if (result != null) {
return result;
}

MethodInfo method = definition.method(name);
return method == null ? null : method.defaultValue();
}

/**
* Returns the value that is associated with the special default "value"
* parameter, also accounting for a value default. Since an annotation's
* defaults are only stored on the annotation's defining class, and not
* usages of the annotation, an index containing the Annotation class must
* be provided as a parameter. If the index does not contain the defining
* annotation class, then an <code>IllegalArgumentException</code> will be
* thrown to prevent non-deterministic results.
*
* <p>
* If the "value" parameter was not specified by this instance, then the
* annotation's <code>ClassInfo</code> is checked for a default value.
* If there is a default, that value is returned. Otherwise null is
* returned.
* </p>
*
* @param index the index containing the defining annotation class
* @return the "value" value, or its default, or null
* @throws IllegalArgumentException if index does not contain the defining
* annotation class
*/
public AnnotationValue valueWithDefault(IndexView index) {
return valueWithDefault(index, "value");
}


/**
* Returns a list of all parameter values on this annotation instance,
* including default values id defined. Since an annotation's defaults are
* only stored on the annotation's defining class, and not usages of the
* annotation, an index containing the Annotation class must be provided as
* a parameter. If the index does not contain the defining annotation class,
* then an <code>IllegalArgumentException</code> will be thrown to prevent
* non-deterministic results.
*
* <p>The order of this list is undefined.</p>
*
* @return the parameter values of this annotation
* @throws IllegalArgumentException if index does not contain the defining
* annotation class
*/
public List<AnnotationValue> valuesWithDefaults(IndexView index) {
ClassInfo definition = index.getClassByName(this.name);
if (definition == null) {
throw new IllegalArgumentException("Index did not contain annotation definition: " + this.name);
}

List<MethodInfo> methods = definition.methods();
ArrayList<AnnotationValue> result = new ArrayList<AnnotationValue>(methods.size());
for (MethodInfo method : methods) {
AnnotationValue value = value(method.name());
if (value == null) {
value = method.defaultValue();
}
if (value != null) {
result.add(value);
}
}

return Collections.unmodifiableList(result);
}

/**
* Returns a list of all parameter values on this annotation instance.
* While random access is allowed, the ordering algorithm
Expand Down
132 changes: 71 additions & 61 deletions src/main/java/org/jboss/jandex/IndexReaderV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
*/
final class IndexReaderV2 extends IndexReaderImpl {
static final int MIN_VERSION = 6;
static final int MAX_VERSION = 6;
static final int MAX_VERSION = 7;
static final int MAX_DATA_VERSION = 4;
private static final byte NULL_TARGET_TAG = 0;
private static final byte FIELD_TAG = 1;
Expand Down Expand Up @@ -108,7 +108,7 @@ Index read(int version) throws IOException {

readTypeTable(stream);
readTypeListTable(stream);
readMethodTable(stream);
readMethodTable(stream, version);
readFieldTable(stream);
return readClasses(stream, annotationsSize, implementorsSize, subclassesSize);
} finally {
Expand Down Expand Up @@ -219,67 +219,70 @@ private AnnotationValue[] readAnnotationValues(PackedDataInputStream stream) thr
AnnotationValue[] values = new AnnotationValue[numValues];

for (int i = 0; i < numValues; i++) {

String name = stringTable[stream.readPackedU32()];
int tag = stream.readByte();
AnnotationValue value;
switch (tag) {
case AVALUE_BYTE:
value = new AnnotationValue.ByteValue(name, stream.readByte());
break;
case AVALUE_SHORT:
value = new AnnotationValue.ShortValue(name, (short) stream.readPackedU32());
break;
case AVALUE_INT:
value = new AnnotationValue.IntegerValue(name, stream.readPackedU32());
break;
case AVALUE_CHAR:
value = new AnnotationValue.CharacterValue(name, (char) stream.readPackedU32());
break;
case AVALUE_FLOAT:
value = new AnnotationValue.FloatValue(name, stream.readFloat());
break;
case AVALUE_DOUBLE:
value = new AnnotationValue.DoubleValue(name, stream.readDouble());
break;
case AVALUE_LONG:
value = new AnnotationValue.LongValue(name, stream.readLong());
break;
case AVALUE_BOOLEAN:
value = new AnnotationValue.BooleanValue(name, stream.readBoolean());
break;
case AVALUE_STRING:
value = new AnnotationValue.StringValue(name, stringTable[stream.readPackedU32()]);
break;
case AVALUE_CLASS:
value = new AnnotationValue.ClassValue(name, typeTable[stream.readPackedU32()]);
break;
case AVALUE_ENUM:
value = new AnnotationValue.EnumValue(name, nameTable[stream.readPackedU32()], stringTable[stream.readPackedU32()]);
break;
case AVALUE_ARRAY:
value = new AnnotationValue.ArrayValue(name, readAnnotationValues(stream));
break;
case AVALUE_NESTED: {
int reference = stream.readPackedU32();
AnnotationInstance nestedInstance = annotationTable[reference];
if (nestedInstance == null) {
nestedInstance = annotationTable[reference] = readAnnotationEntry(stream, null);
}

value = new AnnotationValue.NestedAnnotation(name, nestedInstance);
break;
}
default:
throw new IllegalStateException("Invalid annotation value tag:" + tag);
}

AnnotationValue value = readAnnotationValue(stream);
values[i] = value;
}

return values;
}

private AnnotationValue readAnnotationValue(PackedDataInputStream stream) throws IOException {
String name = stringTable[stream.readPackedU32()];
int tag = stream.readByte();
AnnotationValue value;
switch (tag) {
case AVALUE_BYTE:
value = new AnnotationValue.ByteValue(name, stream.readByte());
break;
case AVALUE_SHORT:
value = new AnnotationValue.ShortValue(name, (short) stream.readPackedU32());
break;
case AVALUE_INT:
value = new AnnotationValue.IntegerValue(name, stream.readPackedU32());
break;
case AVALUE_CHAR:
value = new AnnotationValue.CharacterValue(name, (char) stream.readPackedU32());
break;
case AVALUE_FLOAT:
value = new AnnotationValue.FloatValue(name, stream.readFloat());
break;
case AVALUE_DOUBLE:
value = new AnnotationValue.DoubleValue(name, stream.readDouble());
break;
case AVALUE_LONG:
value = new AnnotationValue.LongValue(name, stream.readLong());
break;
case AVALUE_BOOLEAN:
value = new AnnotationValue.BooleanValue(name, stream.readBoolean());
break;
case AVALUE_STRING:
value = new AnnotationValue.StringValue(name, stringTable[stream.readPackedU32()]);
break;
case AVALUE_CLASS:
value = new AnnotationValue.ClassValue(name, typeTable[stream.readPackedU32()]);
break;
case AVALUE_ENUM:
value = new AnnotationValue.EnumValue(name, nameTable[stream.readPackedU32()], stringTable[stream.readPackedU32()]);
break;
case AVALUE_ARRAY:
value = new AnnotationValue.ArrayValue(name, readAnnotationValues(stream));
break;
case AVALUE_NESTED: {
int reference = stream.readPackedU32();
AnnotationInstance nestedInstance = annotationTable[reference];
if (nestedInstance == null) {
nestedInstance = annotationTable[reference] = readAnnotationEntry(stream, null);
}

value = new AnnotationValue.NestedAnnotation(name, nestedInstance);
break;
}
default:
throw new IllegalStateException("Invalid annotation value tag:" + tag);
}
return value;
}

private AnnotationInstance readAnnotationEntry(PackedDataInputStream stream, AnnotationTarget caller) throws IOException {
DotName name = nameTable[stream.readPackedU32()];
AnnotationTarget target = readAnnotationTarget(stream, caller);
Expand Down Expand Up @@ -418,12 +421,12 @@ private AnnotationTarget readAnnotationTarget(PackedDataInputStream stream, Anno
throw new IllegalStateException("Invalid tag: " + tag);
}

private void readMethodTable(PackedDataInputStream stream) throws IOException {
private void readMethodTable(PackedDataInputStream stream, int version) throws IOException {
// Null holds the first slot
int size = stream.readPackedU32() + 1;
methodTable = new MethodInternal[size];
for (int i = 1; i < size; i++) {
methodTable[i] = readMethodEntry(stream);
methodTable[i] = readMethodEntry(stream, version);
}

}
Expand All @@ -437,7 +440,7 @@ private void readFieldTable(PackedDataInputStream stream) throws IOException {
}
}

private MethodInternal readMethodEntry(PackedDataInputStream stream) throws IOException {
private MethodInternal readMethodEntry(PackedDataInputStream stream, int version) throws IOException {
byte[] name = byteTable[stream.readPackedU32()];
short flags = (short) stream.readPackedU32();
Type[] typeParameters = typeListTable[stream.readPackedU32()];
Expand All @@ -446,12 +449,19 @@ private MethodInternal readMethodEntry(PackedDataInputStream stream) throws IOEx
Type returnType = typeTable[stream.readPackedU32()];
Type[] parameters = typeListTable[stream.readPackedU32()];
Type[] exceptions = typeListTable[stream.readPackedU32()];
AnnotationValue defaultValue = null;
if (version >= 7) {
boolean hasDefaultValue = stream.readByte() > 0;
if (hasDefaultValue) {
defaultValue = readAnnotationValue(stream);
}
}

MethodInfo methodInfo = new MethodInfo();
AnnotationInstance[] annotations = readAnnotations(stream, methodInfo);
MethodInternal methodInternal = new MethodInternal(name, parameters, returnType, flags,
receiverType, typeParameters,
exceptions, annotations);
exceptions, annotations, defaultValue);
methodInfo.setMethodInternal(methodInternal);
return methodInternal;
}
Expand Down
22 changes: 16 additions & 6 deletions src/main/java/org/jboss/jandex/IndexWriterV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
*/
final class IndexWriterV2 extends IndexWriterImpl{
static final int MIN_VERSION = 6;
static final int MAX_VERSION = 6;
static final int MAX_VERSION = 7;

// babelfish (no h)
private static final int MAGIC = 0xBABE1F15;
Expand Down Expand Up @@ -200,7 +200,7 @@ int write(Index index, int version) throws IOException {

writeTypeTable(stream);
writeTypeListTable(stream);
writeMethodTable(stream);
writeMethodTable(stream, version);
writeFieldTable(stream);
writeClasses(stream, index);
stream.flush();
Expand Down Expand Up @@ -251,12 +251,12 @@ private void writeTypeListEntry(PackedDataOutputStream stream, Type[] types) thr
}
}

private void writeMethodTable(PackedDataOutputStream stream) throws IOException {
private void writeMethodTable(PackedDataOutputStream stream, int version) throws IOException {
StrongInternPool<MethodInternal> methodPool = names.methodPool();
stream.writePackedU32(methodPool.size());
Iterator<MethodInternal> iterator = methodPool.iterator();
while (iterator.hasNext()) {
writeMethodEntry(stream, iterator.next());
writeMethodEntry(stream, version, iterator.next());
}
}

Expand All @@ -281,7 +281,7 @@ private void writeFieldEntry(PackedDataOutputStream stream, FieldInternal field)
}
}

private void writeMethodEntry(PackedDataOutputStream stream, MethodInternal method) throws IOException {
private void writeMethodEntry(PackedDataOutputStream stream, int version, MethodInternal method) throws IOException {
stream.writePackedU32(positionOf(method.nameBytes()));
stream.writePackedU32(method.flags());
stream.writePackedU32(positionOf(method.typeParameterArray()));
Expand All @@ -290,6 +290,13 @@ private void writeMethodEntry(PackedDataOutputStream stream, MethodInternal meth
stream.writePackedU32(positionOf(method.returnType()));
stream.writePackedU32(positionOf(method.parameterArray()));
stream.writePackedU32(positionOf(method.exceptionArray()));
if (version >= 7) {
AnnotationValue defaultValue = method.defaultValue();
stream.writeByte(defaultValue != null ? 1 : 0);
if (defaultValue != null) {
writeAnnotationValue(stream, defaultValue);
}
}

AnnotationInstance[] annotations = method.annotationArray();
stream.writePackedU32(annotations.length);
Expand Down Expand Up @@ -723,9 +730,12 @@ private void deepIntern(MethodInternal method) {
addTypeList(method.typeParameterArray());
addTypeList(method.parameterArray());
addTypeList(method.exceptionArray());
AnnotationValue defaultValue = method.defaultValue();
if (defaultValue != null) {
buildAValueEntries(defaultValue);
}
names.intern(method.nameBytes());
names.intern(method);

}

private void addEnclosingMethod(ClassInfo.EnclosingMethodInfo enclosingMethod) {
Expand Down
Loading

0 comments on commit c208ff5

Please sign in to comment.