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