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.tool; 27 28 import java.io.PrintWriter; 29 import java.util.List; 30 31 import jdk.jfr.EventType; 32 import jdk.jfr.ValueDescriptor; 33 import jdk.jfr.consumer.RecordedEvent; 34 import jdk.jfr.consumer.RecordedFrame; 35 import jdk.jfr.consumer.RecordedObject; 36 37 final class XMLWriter extends EventPrintWriter { 38 public XMLWriter(PrintWriter destination) { 39 super(destination); 40 } 41 42 @Override 43 protected void printBegin() { 44 println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 45 println("<recording xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"); 46 indent(); 47 printIndent(); 48 println("<events>"); 49 indent(); 50 } 51 52 @Override 53 protected void printEnd() { 54 retract(); 55 printIndent(); 56 println("</events>"); 57 retract(); 58 println("</recording>"); 59 } 60 61 @Override 62 protected void print(List<RecordedEvent> events) { 63 for (RecordedEvent event : events) { 64 printEvent(event); 65 } 66 } 67 68 private void printEvent(RecordedEvent event) { 69 EventType type = event.getEventType(); 70 printIndent(); 71 print("<event"); 72 printAttribute("type", type.getName()); 73 print(">"); 74 println(); 75 indent(); 76 for (ValueDescriptor v : event.getFields()) { 77 printValueDescriptor(v, getValue(event, v), -1); 78 } 79 retract(); 80 printIndent(); 81 println("</event>"); 82 println(); 83 } 84 85 private void printAttribute(String name, String value) { 86 print(" ", name, "=\"", value, "\""); 87 } 88 89 public void printObject(RecordedObject struct) { 90 println(); 91 indent(); 92 for (ValueDescriptor v : struct.getFields()) { 93 printValueDescriptor(v, getValue(struct, v), -1); 94 } 95 retract(); 96 } 97 98 private void printArray(ValueDescriptor v, Object[] array) { 99 println(); 100 indent(); 101 int depth = 0; 102 for (int index = 0; index < array.length; index++) { 103 Object arrayElement = array[index]; 104 if (!(arrayElement instanceof RecordedFrame) || depth < getStackDepth()) { 105 printValueDescriptor(v, array[index], index); 106 } 107 depth++; 108 } 109 retract(); 110 } 111 112 private void printValueDescriptor(ValueDescriptor vd, Object value, int index) { 113 boolean arrayElement = index != -1; 114 String name = arrayElement ? null : vd.getName(); 115 if (vd.isArray() && !arrayElement) { 116 if (printBeginElement("array", name, value, index)) { 117 printArray(vd, (Object[]) value); 118 printIndent(); 119 printEndElement("array"); 120 } 121 return; 122 } 123 if (!vd.getFields().isEmpty()) { 124 if (printBeginElement("struct", name, value, index)) { 125 printObject((RecordedObject) value); 126 printIndent(); 127 printEndElement("struct"); 128 } 129 return; 130 } 131 if (printBeginElement("value", name, value, index)) { 132 printEscaped(String.valueOf(value)); 133 printEndElement("value"); 134 } 135 } 136 137 private boolean printBeginElement(String elementName, String name, Object value, int index) { 138 printIndent(); 139 print("<", elementName); 140 if (name != null) { 141 printAttribute("name", name); 142 } 143 if (index != -1) { 144 printAttribute("index", Integer.toString(index)); 145 } 146 if (value == null) { 147 printAttribute("xsi:nil", "true"); 148 println("/>"); 149 return false; 150 } 151 if (value.getClass().isArray()) { 152 Object[] array = (Object[]) value; 153 printAttribute("size", Integer.toString(array.length)); 154 } 155 print(">"); 156 return true; 157 } 158 159 private void printEndElement(String elementName) { 160 print("</"); 161 print(elementName); 162 println(">"); 163 } 164 165 private void printEscaped(String text) { 166 for (int i = 0; i < text.length(); i++) { 167 printEscaped(text.charAt(i)); 168 } 169 } 170 171 private void printEscaped(char c) { 172 if (c == 34) { 173 print("""); 174 return; 175 } 176 if (c == 38) { 177 print("&"); 178 return; 179 } 180 if (c == 39) { 181 print("'"); 182 return; 183 } 184 if (c == 60) { 185 print("<"); 186 return; 187 } 188 if (c == 62) { 189 print(">"); 190 return; 191 } 192 if (c > 0x7F) { 193 print("&#"); 194 print((int) c); 195 print(';'); 196 return; 197 } 198 print(c); 199 } 200 }