Skip to content

Commit

Permalink
JMC-7155: [JFR Writer] Complete the annotation handling code
Browse files Browse the repository at this point in the history
  • Loading branch information
jbachorik committed Mar 1, 2021
1 parent e52a361 commit a4d9ac0
Show file tree
Hide file tree
Showing 19 changed files with 460 additions and 109 deletions.
@@ -0,0 +1,32 @@
package org.openjdk.jmc.flightrecorder.writer;

import org.openjdk.jmc.flightrecorder.writer.api.Annotation;
import org.openjdk.jmc.flightrecorder.writer.api.AnnotationElementBuilder;
import org.openjdk.jmc.flightrecorder.writer.api.Type;
import org.openjdk.jmc.flightrecorder.writer.api.TypedValue;
import org.openjdk.jmc.flightrecorder.writer.api.TypedValueBuilder;

import java.util.function.Consumer;

final class AnnotationElementBuilderImpl implements AnnotationElementBuilder {
private final Type type;

AnnotationElementBuilderImpl(Type type) {
this.type = type;
}

@Override
public AnnotationElementBuilder addArgument(String name, TypedValue value) {
return this;
}

@Override
public AnnotationElementBuilder addArgument(String name, Consumer<TypedValueBuilder> builderCallback) {
return this;
}

@Override
public Annotation build() {
return new Annotation(type, (String) null);
}
}
Expand Up @@ -45,6 +45,8 @@

import org.openjdk.jmc.flightrecorder.writer.api.Annotation;
import org.openjdk.jmc.flightrecorder.writer.api.NamedType;
import org.openjdk.jmc.flightrecorder.writer.api.TypedFieldValue;
import org.openjdk.jmc.flightrecorder.writer.api.TypedValue;
import org.openjdk.jmc.flightrecorder.writer.api.Types;

/** JFR type repository class. */
Expand Down Expand Up @@ -304,8 +306,21 @@ private void storeTypeStrings(TypeImpl type) {

private void storeAnnotationStrings(List<Annotation> annotations) {
for (Annotation annotation : annotations) {
if (annotation.getValue() != null) {
storeString(annotation.getValue());
for (Map.Entry<String, ? extends TypedFieldValue> entry : annotation.getAttributes().entrySet()) {
TypedFieldValue typedValue = entry.getValue();
// value arrays are encoded as 'attributeName-N' where N starts at 0
if (typedValue.getField().isArray()) {
TypedValue[] vals = typedValue.getValues();
for (int i = 0; i < vals.length; i++) {
TypedValue val = vals[i];
storeString(entry.getKey() + "-" + i);
storeString(Objects.toString(val.getValue()));
}
} else {
Object val = typedValue.getValue() != null ? typedValue.getValue().getValue() : null;
storeString(entry.getKey());
storeString(Objects.toString(val));
}
}
}
}
Expand Down Expand Up @@ -433,10 +448,28 @@ private void writeFieldAnnotations(LEB128Writer writer, TypedFieldImpl field) {
private void writeAnnotation(LEB128Writer writer, Annotation annotation) {
writer.writeInt(stringIndex(ANNOTATION_KEY));

writer.writeInt(annotation.getValue() != null ? 2 : 1) // number of attributes
.writeInt(stringIndex(CLASS_KEY)).writeInt(stringIndex(String.valueOf(annotation.getType().getId())));
if (annotation.getValue() != null) {
writer.writeInt(stringIndex(VALUE_KEY)).writeInt(stringIndex(annotation.getValue()));
int len = 1 + annotation.getAttributes().size();
for (TypedFieldValue value : annotation.getAttributes().values()) {
if (value.getField().isArray()) {
len += (value.getValues().length - 1); // add the number of synthetic attributes and remove the base one
}
}
writer.writeInt(len).writeInt(stringIndex(CLASS_KEY))
.writeInt(stringIndex(String.valueOf(annotation.getType().getId())));
for (Map.Entry<String, ? extends TypedFieldValue> entry : annotation.getAttributes().entrySet()) {
TypedFieldValue typedValue = entry.getValue();
if (typedValue.getField().isArray()) {
// value arrays are encoded as 'attributeName-N' where N starts at 0
TypedValue[] vals = typedValue.getValues();
for (int i = 0; i < vals.length; i++) {
TypedValue val = vals[i];
writer.writeInt(stringIndex(entry.getKey() + "-" + i))
.writeInt(stringIndex(Objects.toString(val.getValue())));
}
} else {
Object val = typedValue.getValue() != null ? typedValue.getValue().getValue() : null;
writer.writeInt(stringIndex(entry.getKey())).writeInt(stringIndex(Objects.toString(val)));
}
}
writer.writeInt(0); // no sub-elements
}
Expand Down
Expand Up @@ -39,6 +39,7 @@
import org.openjdk.jmc.flightrecorder.writer.api.Type;
import org.openjdk.jmc.flightrecorder.writer.api.TypedField;
import org.openjdk.jmc.flightrecorder.writer.api.TypedFieldBuilder;
import org.openjdk.jmc.flightrecorder.writer.api.TypedValueBuilder;
import org.openjdk.jmc.flightrecorder.writer.api.Types;

import java.util.ArrayList;
Expand Down Expand Up @@ -98,7 +99,7 @@ public TypeStructureBuilder addFields(TypedField field1, TypedField field2, Type

@Override
public TypeStructureBuilderImpl addAnnotation(Type type) {
return addAnnotation(type, null);
return addAnnotation(type, (String) null);
}

@Override
Expand All @@ -107,6 +108,31 @@ public TypeStructureBuilderImpl addAnnotation(Type type, String value) {
return this;
}

@Override
public TypeStructureBuilderImpl addAnnotation(Types.Predefined type) {
return addAnnotation(types.getType(type));
}

@Override
public TypeStructureBuilderImpl addAnnotation(Types.Predefined type, String value) {
return addAnnotation(types.getType(type), value);
}

@Override
public TypeStructureBuilderImpl addAnnotation(Type type, Consumer<TypedValueBuilder> builderCallback) {
TypedValueBuilderImpl impl = new TypedValueBuilderImpl((TypeImpl) type);
if (builderCallback != null) {
builderCallback.accept(impl);
}
annotations.add(new Annotation(type, impl.build()));
return this;
}

@Override
public TypeStructureBuilderImpl addAnnotation(Types.Predefined type, Consumer<TypedValueBuilder> builderCallback) {
return addAnnotation(types.getType(type), builderCallback);
}

@Override
public Type selfType() {
return SelfType.INSTANCE;
Expand Down
Expand Up @@ -36,9 +36,12 @@
import org.openjdk.jmc.flightrecorder.writer.api.Annotation;
import org.openjdk.jmc.flightrecorder.writer.api.Type;
import org.openjdk.jmc.flightrecorder.writer.api.TypedFieldBuilder;
import org.openjdk.jmc.flightrecorder.writer.api.TypedValueBuilder;
import org.openjdk.jmc.flightrecorder.writer.api.Types;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

final class TypedFieldBuilderImpl implements TypedFieldBuilder {
private final TypesImpl types;
Expand All @@ -55,7 +58,7 @@ final class TypedFieldBuilderImpl implements TypedFieldBuilder {

@Override
public TypedFieldBuilderImpl addAnnotation(Type type) {
return addAnnotation(type, null);
return addAnnotation(type, (String) null);
}

@Override
Expand All @@ -70,10 +73,25 @@ public TypedFieldBuilderImpl addAnnotation(TypesImpl.Predefined type) {
}

@Override
public TypedFieldBuilderImpl addAnnotation(TypesImpl.Predefined type, String value) {
public TypedFieldBuilderImpl addAnnotation(Types.Predefined type, String value) {
return addAnnotation(types.getType(type), value);
}

@Override
public TypedFieldBuilder addAnnotation(Type type, Consumer<TypedValueBuilder> builderCallback) {
TypedValueBuilderImpl impl = new TypedValueBuilderImpl((TypeImpl) type);
if (builderCallback != null) {
builderCallback.accept(impl);
}
annotations.add(new Annotation(type, impl.build()));
return this;
}

@Override
public TypedFieldBuilder addAnnotation(Types.Predefined type, Consumer<TypedValueBuilder> builderCallback) {
return addAnnotation(types.getType(type), builderCallback);
}

@Override
public TypedFieldBuilderImpl asArray() {
asArray = true;
Expand Down
Expand Up @@ -49,7 +49,7 @@ public final class TypedFieldImpl implements org.openjdk.jmc.flightrecorder.writ
private final boolean isArray;
private final List<Annotation> annotations;

TypedFieldImpl(TypeImpl type, String name) {
public TypedFieldImpl(TypeImpl type, String name) {
this(type, name, false, Collections.emptyList());
}

Expand Down
Expand Up @@ -44,7 +44,7 @@
import java.util.Objects;
import java.util.function.Consumer;

final class TypedValueImpl implements TypedValue {
public final class TypedValueImpl implements TypedValue {
private int hashcode = 0;

private final TypeImpl type;
Expand Down
Expand Up @@ -85,19 +85,23 @@ private void registerJdkTypes() {
});
getOrAdd(JDK.ANNOTATION_TIMESTAMP, ANNOTATION_SUPER_TYPE_NAME, builder -> {
builder.addField("value", Builtin.STRING).addAnnotation(annotationNameType, "jdk.jfr.Timestamp")
.addAnnotation(annotationContentTypeType, null).addAnnotation(annotationLabelType, "Timestamp")
.addAnnotation(annotationContentTypeType).addAnnotation(annotationLabelType, "Timestamp")
.addAnnotation(annotationDescriptionType, "A point in time");
});
getOrAdd(JDK.ANNOTATION_TIMESPAN, ANNOTATION_SUPER_TYPE_NAME, builder -> {
builder.addField("value", Builtin.STRING).addAnnotation(annotationNameType, "jdk.jfr.Timespan")
.addAnnotation(annotationContentTypeType, null).addAnnotation(annotationLabelType, "Timespan")
.addAnnotation(annotationContentTypeType).addAnnotation(annotationLabelType, "Timespan")
.addAnnotation(annotationDescriptionType, "A duration, measured in nanoseconds by default");
});
getOrAdd(JDK.ANNOTATION_UNSIGNED, ANNOTATION_SUPER_TYPE_NAME, builder -> {
builder.addField("value", Builtin.STRING).addAnnotation(annotationNameType, "jdk.jfr.Unsigned")
.addAnnotation(annotationContentTypeType, null).addAnnotation(annotationLabelType, "Unsigned value")
.addAnnotation(annotationContentTypeType).addAnnotation(annotationLabelType, "Unsigned value")
.addAnnotation(annotationDescriptionType, "Value should be interpreted as unsigned data type");
});
getOrAdd(JDK.ANNOTATION_CATEGORY, ANNOTATION_SUPER_TYPE_NAME, builder -> {
builder.addField("value", STRING, TypedFieldBuilder::asArray).addAnnotation(annotationNameType,
"jdk.jfr.Category");
});

getOrAdd(JDK.TICKSPAN, builder -> {
builder.addField("tickSpan", Builtin.LONG);
Expand Down
@@ -0,0 +1,67 @@
package org.openjdk.jmc.flightrecorder.writer.api;

import java.util.function.Consumer;

public interface AnnotatedElementBuilder<T extends AnnotatedElementBuilder<?>> {
/**
* Add an annotation of the given type
*
* @param type
* the annotation type
* @return a {@linkplain AnnotatedElementBuilder} instance for invocation chaining
*/
T addAnnotation(Type type);

/**
* Add an annotation of the given type and with the given value
*
* @param type
* the annotation type
* @param value
* the annotation value
* @return a {@linkplain AnnotatedElementBuilder} instance for invocation chaining
*/
T addAnnotation(Type type, String value);

/**
* Add a predefined annotation
*
* @param type
* predefined annotation type
* @return a {@linkplain AnnotatedElementBuilder} instance for invocation chaining
*/
T addAnnotation(Types.Predefined type);

/**
* Add a predefined annotation with a value
*
* @param type
* predefined annotation type
* @param value
* annotation value
* @return a {@linkplain AnnotatedElementBuilder} instance for invocation chaining
*/
T addAnnotation(Types.Predefined type, String value);

/**
* Add an annotation of the given type and with the given values array
*
* @param type
* the annotation type
* @param builderCallback
* the annotation attributes builder callback
* @return a {@linkplain AnnotatedElementBuilder} instance for invocation chaining
*/
T addAnnotation(Type type, Consumer<TypedValueBuilder> builderCallback);

/**
* Add an annotation of the given type and with the given values array
*
* @param type
* the annotation type
* @param builderCallback
* the annotation attributes builder callback
* @return a {@linkplain AnnotatedElementBuilder} instance for invocation chaining
*/
T addAnnotation(Types.Predefined type, Consumer<TypedValueBuilder> builderCallback);
}

0 comments on commit a4d9ac0

Please sign in to comment.