|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package jdk.jfr.internal; |
|
|
|
import java.io.DataInput; |
|
import java.io.DataOutput; |
|
import java.io.IOException; |
|
import java.util.ArrayList; |
|
import java.util.Collection; |
|
import java.util.List; |
|
import java.util.Locale; |
|
import java.util.TimeZone; |
|
|
|
import jdk.jfr.EventType; |
|
|
|
|
|
|
|
*/ |
|
public final class MetadataDescriptor { |
|
|
|
static final class Attribute { |
|
final String name; |
|
final String value; |
|
|
|
private Attribute(String name, String value) { |
|
this.name = name; |
|
this.value = value; |
|
} |
|
} |
|
|
|
static final class Element { |
|
final String name; |
|
final List<Element> elements = new ArrayList<>(); |
|
final List<Attribute> attributes = new ArrayList<>(); |
|
|
|
Element(String name) { |
|
this.name = name; |
|
} |
|
|
|
long longValue(String name) { |
|
String v = attribute(name); |
|
if (v != null) |
|
return Long.parseLong(v); |
|
else |
|
throw new IllegalArgumentException(name); |
|
} |
|
|
|
String attribute(String name) { |
|
for (Attribute a : attributes) { |
|
if (a.name.equals(name)) { |
|
return a.value; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
StringBuilder sb = new StringBuilder(); |
|
try { |
|
prettyPrintXML(sb, "", this); |
|
} catch (IOException e) { |
|
// should not happen |
|
} |
|
return sb.toString(); |
|
} |
|
|
|
long attribute(String name, long defaultValue) { |
|
String text = attribute(name); |
|
if (text == null) { |
|
return defaultValue; |
|
} |
|
return Long.parseLong(text); |
|
} |
|
|
|
String attribute(String name, String defaultValue) { |
|
String text = attribute(name); |
|
if (text == null) { |
|
return defaultValue; |
|
} |
|
return text; |
|
} |
|
|
|
List<Element> elements(String... names) { |
|
List<Element> filteredElements = new ArrayList<>(); |
|
for (String name : names) { |
|
for (Element e : elements) { |
|
if (e.name.equals(name)) { |
|
filteredElements.add(e); |
|
} |
|
} |
|
} |
|
return filteredElements; |
|
} |
|
|
|
void add(Element element) { |
|
elements.add(element); |
|
} |
|
|
|
void addAttribute(String name, Object value) { |
|
attributes.add(new Attribute(name, String.valueOf(value))); |
|
} |
|
|
|
Element newChild(String name) { |
|
Element e = new Element(name); |
|
elements.add(e); |
|
return e; |
|
} |
|
|
|
public void addArrayAttribute(Element element, String name, Object value) { |
|
String typeName = value.getClass().getComponentType().getName(); |
|
switch (typeName) { |
|
case "int": |
|
int[] ints = (int[]) value; |
|
for (int i = 0; i < ints.length; i++) { |
|
addAttribute(name + "-" + i , ints[i]); |
|
} |
|
break; |
|
case "long": |
|
long[] longs = (long[]) value; |
|
for (int i = 0; i < longs.length; i++) { |
|
addAttribute(name + "-" + i , longs[i]); |
|
} |
|
break; |
|
case "float": |
|
float[] floats = (float[]) value; |
|
for (int i = 0; i < floats.length; i++) { |
|
addAttribute(name + "-" + i , floats[i]); |
|
} |
|
break; |
|
|
|
case "double": |
|
double[] doubles = (double[]) value; |
|
for (int i = 0; i < doubles.length; i++) { |
|
addAttribute(name + "-" + i , doubles[i]); |
|
} |
|
break; |
|
case "short": |
|
short[] shorts = (short[]) value; |
|
for (int i = 0; i < shorts.length; i++) { |
|
addAttribute(name + "-" + i , shorts[i]); |
|
} |
|
break; |
|
case "char": |
|
char[] chars = (char[]) value; |
|
for (int i = 0; i < chars.length; i++) { |
|
addAttribute(name + "-" + i , chars[i]); |
|
} |
|
break; |
|
case "byte": |
|
byte[] bytes = (byte[]) value; |
|
for (int i = 0; i < bytes.length; i++) { |
|
addAttribute(name + "-" + i , bytes[i]); |
|
} |
|
break; |
|
case "boolean": |
|
boolean[] booleans = (boolean[]) value; |
|
for (int i = 0; i < booleans.length; i++) { |
|
addAttribute(name + "-" + i , booleans[i]); |
|
} |
|
break; |
|
case "java.lang.String": |
|
String[] strings = (String[]) value; |
|
for (int i = 0; i < strings.length; i++) { |
|
addAttribute(name + "-" + i , strings[i]); |
|
} |
|
break; |
|
default: |
|
throw new InternalError("Array type of " + typeName + " is not supported"); |
|
} |
|
} |
|
} |
|
|
|
static final String ATTRIBUTE_ID = "id"; |
|
static final String ATTRIBUTE_SIMPLE_TYPE = "simpleType"; |
|
static final String ATTRIBUTE_GMT_OFFSET = "gmtOffset"; |
|
static final String ATTRIBUTE_LOCALE = "locale"; |
|
static final String ELEMENT_TYPE = "class"; |
|
static final String ELEMENT_SETTING = "setting"; |
|
static final String ELEMENT_ANNOTATION = "annotation"; |
|
static final String ELEMENT_FIELD = "field"; |
|
static final String ATTRIBUTE_SUPER_TYPE = "superType"; |
|
static final String ATTRIBUTE_TYPE_ID = "class"; |
|
static final String ATTRIBUTE_DIMENSION = "dimension"; |
|
static final String ATTRIBUTE_NAME = "name"; |
|
static final String ATTRIBUTE_CONSTANT_POOL = "constantPool"; |
|
static final String ATTRIBUTE_DEFAULT_VALUE = "defaultValue"; |
|
|
|
final List<EventType> eventTypes = new ArrayList<>(); |
|
final Collection<Type> types = new ArrayList<>(); |
|
long gmtOffset; |
|
String locale; |
|
Element root; |
|
|
|
|
|
MetadataDescriptor() { |
|
} |
|
|
|
private static void prettyPrintXML(Appendable sb, String indent, Element e) throws IOException { |
|
sb.append(indent + "<" + e.name); |
|
for (Attribute a : e.attributes) { |
|
sb.append(" ").append(a.name).append("=\"").append(a.value).append("\""); |
|
} |
|
if (e.elements.size() == 0) { |
|
sb.append("/"); |
|
} |
|
sb.append(">\n"); |
|
for (Element child : e.elements) { |
|
prettyPrintXML(sb, indent + " ", child); |
|
} |
|
if (e.elements.size() != 0) { |
|
sb.append(indent).append("</").append(e.name).append(">\n"); |
|
} |
|
} |
|
|
|
public Collection<Type> getTypes() { |
|
return types; |
|
} |
|
|
|
public List<EventType> getEventTypes() { |
|
return eventTypes; |
|
} |
|
|
|
public int getGMTOffset() { |
|
return (int) gmtOffset; |
|
} |
|
|
|
public String getLocale() { |
|
return locale; |
|
} |
|
|
|
public static MetadataDescriptor read(DataInput input) throws IOException { |
|
MetadataReader r = new MetadataReader(input); |
|
return r.getDescriptor(); |
|
} |
|
|
|
static void write(List<Type> types, DataOutput output) throws IOException { |
|
MetadataDescriptor m = new MetadataDescriptor(); |
|
m.locale = Locale.getDefault().toString(); |
|
m.gmtOffset = TimeZone.getDefault().getRawOffset(); |
|
m.types.addAll(types); |
|
MetadataWriter w = new MetadataWriter(m); |
|
w.writeBinary(output); |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
return root.toString(); |
|
} |
|
} |