--- /dev/null 2018-06-17 23:18:20.806999507 +0800 +++ new/src/share/classes/jdk/jfr/internal/MetadataDescriptor.java 2019-01-29 10:59:34.602704222 +0800 @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +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; + +/** + * Metadata about a chunk + */ +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 elements = new ArrayList<>(); + final List 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 elements(String... names) { + List 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 eventTypes = new ArrayList<>(); + final Collection types = new ArrayList<>(); + long gmtOffset; + String locale; + Element root; + + // package private + 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("\n"); + } + } + + public Collection getTypes() { + return types; + } + + public List 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 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(); + } +}