1 /* 2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.internal; 27 28 import java.io.DataInput; 29 import java.io.DataOutput; 30 import java.io.IOException; 31 import java.util.ArrayList; 32 import java.util.Collection; 33 import java.util.List; 34 import java.util.Locale; 35 import java.util.TimeZone; 36 37 import jdk.jfr.EventType; 38 39 /** 40 * Metadata about a chunk 41 */ 42 public final class MetadataDescriptor { 43 44 static final class Attribute { 45 final String name; 46 final String value; 47 48 private Attribute(String name, String value) { 49 this.name = name; 50 this.value = value; 51 } 52 } 53 54 static final class Element { 55 final String name; 56 final List<Element> elements = new ArrayList<>(); 57 final List<Attribute> attributes = new ArrayList<>(); 58 59 Element(String name) { 60 this.name = name; 61 } 62 63 long longValue(String name) { 64 String v = attribute(name); 65 if (v != null) 66 return Long.parseLong(v); 67 else 68 throw new IllegalArgumentException(name); 69 } 70 71 String attribute(String name) { 72 for (Attribute a : attributes) { 73 if (a.name.equals(name)) { 74 return a.value; 75 } 76 } 77 return null; 78 } 79 80 @Override 81 public String toString() { 82 StringBuilder sb = new StringBuilder(); 83 try { 84 prettyPrintXML(sb, "", this); 85 } catch (IOException e) { 86 // should not happen 87 } 88 return sb.toString(); 89 } 90 91 long attribute(String name, long defaultValue) { 92 String text = attribute(name); 93 if (text == null) { 94 return defaultValue; 95 } 96 return Long.parseLong(text); 97 } 98 99 String attribute(String name, String defaultValue) { 100 String text = attribute(name); 101 if (text == null) { 102 return defaultValue; 103 } 104 return text; 105 } 106 107 List<Element> elements(String... names) { 108 List<Element> filteredElements = new ArrayList<>(); 109 for (String name : names) { 110 for (Element e : elements) { 111 if (e.name.equals(name)) { 112 filteredElements.add(e); 113 } 114 } 115 } 116 return filteredElements; 117 } 118 119 void add(Element element) { 120 elements.add(element); 121 } 122 123 void addAttribute(String name, Object value) { 124 attributes.add(new Attribute(name, String.valueOf(value))); 125 } 126 127 Element newChild(String name) { 128 Element e = new Element(name); 129 elements.add(e); 130 return e; 131 } 132 133 public void addArrayAttribute(Element element, String name, Object value) { 134 String typeName = value.getClass().getComponentType().getName(); 135 switch (typeName) { 136 case "int": 137 int[] ints = (int[]) value; 138 for (int i = 0; i < ints.length; i++) { 139 addAttribute(name + "-" + i , ints[i]); 140 } 141 break; 142 case "long": 143 long[] longs = (long[]) value; 144 for (int i = 0; i < longs.length; i++) { 145 addAttribute(name + "-" + i , longs[i]); 146 } 147 break; 148 case "float": 149 float[] floats = (float[]) value; 150 for (int i = 0; i < floats.length; i++) { 151 addAttribute(name + "-" + i , floats[i]); 152 } 153 break; 154 155 case "double": 156 double[] doubles = (double[]) value; 157 for (int i = 0; i < doubles.length; i++) { 158 addAttribute(name + "-" + i , doubles[i]); 159 } 160 break; 161 case "short": 162 short[] shorts = (short[]) value; 163 for (int i = 0; i < shorts.length; i++) { 164 addAttribute(name + "-" + i , shorts[i]); 165 } 166 break; 167 case "char": 168 char[] chars = (char[]) value; 169 for (int i = 0; i < chars.length; i++) { 170 addAttribute(name + "-" + i , chars[i]); 171 } 172 break; 173 case "byte": 174 byte[] bytes = (byte[]) value; 175 for (int i = 0; i < bytes.length; i++) { 176 addAttribute(name + "-" + i , bytes[i]); 177 } 178 break; 179 case "boolean": 180 boolean[] booleans = (boolean[]) value; 181 for (int i = 0; i < booleans.length; i++) { 182 addAttribute(name + "-" + i , booleans[i]); 183 } 184 break; 185 case "java.lang.String": 186 String[] strings = (String[]) value; 187 for (int i = 0; i < strings.length; i++) { 188 addAttribute(name + "-" + i , strings[i]); 189 } 190 break; 191 default: 192 throw new InternalError("Array type of " + typeName + " is not supported"); 193 } 194 } 195 } 196 197 static final String ATTRIBUTE_ID = "id"; 198 static final String ATTRIBUTE_SIMPLE_TYPE = "simpleType"; 199 static final String ATTRIBUTE_GMT_OFFSET = "gmtOffset"; 200 static final String ATTRIBUTE_LOCALE = "locale"; 201 static final String ELEMENT_TYPE = "class"; 202 static final String ELEMENT_SETTING = "setting"; 203 static final String ELEMENT_ANNOTATION = "annotation"; 204 static final String ELEMENT_FIELD = "field"; 205 static final String ATTRIBUTE_SUPER_TYPE = "superType"; 206 static final String ATTRIBUTE_TYPE_ID = "class"; 207 static final String ATTRIBUTE_DIMENSION = "dimension"; 208 static final String ATTRIBUTE_NAME = "name"; 209 static final String ATTRIBUTE_CONSTANT_POOL = "constantPool"; 210 static final String ATTRIBUTE_DEFAULT_VALUE = "defaultValue"; 211 212 final List<EventType> eventTypes = new ArrayList<>(); 213 final Collection<Type> types = new ArrayList<>(); 214 long gmtOffset; 215 String locale; 216 Element root; 217 218 // package private 219 MetadataDescriptor() { 220 } 221 222 private static void prettyPrintXML(Appendable sb, String indent, Element e) throws IOException { 223 sb.append(indent + "<" + e.name); 224 for (Attribute a : e.attributes) { 225 sb.append(" ").append(a.name).append("=\"").append(a.value).append("\""); 226 } 227 if (e.elements.size() == 0) { 228 sb.append("/"); 229 } 230 sb.append(">\n"); 231 for (Element child : e.elements) { 232 prettyPrintXML(sb, indent + " ", child); 233 } 234 if (e.elements.size() != 0) { 235 sb.append(indent).append("</").append(e.name).append(">\n"); 236 } 237 } 238 239 public Collection<Type> getTypes() { 240 return types; 241 } 242 243 public List<EventType> getEventTypes() { 244 return eventTypes; 245 } 246 247 public int getGMTOffset() { 248 return (int) gmtOffset; 249 } 250 251 public String getLocale() { 252 return locale; 253 } 254 255 public static MetadataDescriptor read(DataInput input) throws IOException { 256 MetadataReader r = new MetadataReader(input); 257 return r.getDescriptor(); 258 } 259 260 static void write(List<Type> types, DataOutput output) throws IOException { 261 MetadataDescriptor m = new MetadataDescriptor(); 262 m.locale = Locale.getDefault().toString(); 263 m.gmtOffset = TimeZone.getDefault().getRawOffset(); 264 m.types.addAll(types); 265 MetadataWriter w = new MetadataWriter(m); 266 w.writeBinary(output); 267 } 268 269 @Override 270 public String toString() { 271 return root.toString(); 272 } 273 }