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 {
XMLWriter(PrintWriter destination)38     public XMLWriter(PrintWriter destination) {
39         super(destination);
40     }
41 
42     @Override
printBegin()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
printEnd()53     protected void printEnd() {
54         retract();
55         printIndent();
56         println("</events>");
57         retract();
58         println("</recording>");
59     }
60 
61     @Override
print(List<RecordedEvent> events)62     protected void print(List<RecordedEvent> events) {
63         for (RecordedEvent event : events) {
64             printEvent(event);
65         }
66     }
67 
printEvent(RecordedEvent event)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 
printAttribute(String name, String value)85     private void printAttribute(String name, String value) {
86         print(" ", name, "=\"", value, "\"");
87     }
88 
printObject(RecordedObject struct)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 
printArray(ValueDescriptor v, Object[] array)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 
printValueDescriptor(ValueDescriptor vd, Object value, int index)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 
printBeginElement(String elementName, String name, Object value, int index)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 
printEndElement(String elementName)159     private void printEndElement(String elementName) {
160         print("</");
161         print(elementName);
162         println(">");
163     }
164 
printEscaped(String text)165     private void printEscaped(String text) {
166         for (int i = 0; i < text.length(); i++) {
167             printEscaped(text.charAt(i));
168         }
169     }
170 
printEscaped(char c)171     private void printEscaped(char c) {
172         if (c == 34) {
173             print("&quot;");
174             return;
175         }
176         if (c == 38) {
177             print("&amp;");
178             return;
179         }
180         if (c == 39) {
181             print("&apos;");
182             return;
183         }
184         if (c == 60) {
185             print("&lt;");
186             return;
187         }
188         if (c == 62) {
189             print("&gt;");
190             return;
191         }
192         if (c > 0x7F) {
193             print("&#");
194             print((int) c);
195             print(';');
196             return;
197         }
198         print(c);
199     }
200 }
201