src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/JSONWriter.java
changeset 50113 caf115bb98ad
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     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.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 JSONWriter extends StructuredWriter {
       
    39 
       
    40     public JSONWriter(PrintWriter writer) {
       
    41         super(writer);
       
    42     }
       
    43 
       
    44     public void print(Path source) throws IOException {
       
    45         try (RecordingFile es = new RecordingFile(source)) {
       
    46             printObjectBegin();
       
    47             printRecording(es);
       
    48             printObjectEnd();
       
    49             flush();
       
    50         }
       
    51     }
       
    52 
       
    53     private void printRecording(RecordingFile es) throws IOException {
       
    54         printDataStructureName("recording");
       
    55         printObjectBegin();
       
    56         printEvents(es);
       
    57         printObjectEnd();
       
    58     }
       
    59 
       
    60     private void printEvents(RecordingFile es) throws IOException {
       
    61         printDataStructureName("events");
       
    62         printArrayBegin();
       
    63         boolean first = true;
       
    64         while (es.hasMoreEvents()) {
       
    65             RecordedEvent e = es.readEvent();
       
    66             printNewDataStructure(first, true, null);
       
    67             printEvent(e);
       
    68             flush();
       
    69             first = false;
       
    70         }
       
    71         printArrayEnd();
       
    72     }
       
    73 
       
    74     private void printEvent(RecordedEvent e) {
       
    75         printObjectBegin();
       
    76         EventType type = e.getEventType();
       
    77         printValue(true, false, "name", type.getName());
       
    78         printValue(false, false, "typeId", type.getId());
       
    79         printValue(false, false, "startTime", e.getStartTime());
       
    80         printValue(false, false, "duration", e.getDuration());
       
    81         printNewDataStructure(false, false, "values");
       
    82         printObject(e);
       
    83         printObjectEnd();
       
    84     }
       
    85 
       
    86     void printValue(boolean first, boolean arrayElement, String name, Object value) {
       
    87         printNewDataStructure(first, arrayElement, name);
       
    88         if (!printIfNull(value)) {
       
    89             if (value instanceof Boolean) {
       
    90                 printAsString(value);
       
    91                 return;
       
    92             }
       
    93             if (value instanceof Double) {
       
    94                 Double dValue = (Double) value;
       
    95                 if (Double.isNaN(dValue) || Double.isInfinite(dValue)) {
       
    96                     printNull();
       
    97                     return;
       
    98                 }
       
    99                 printAsString(value);
       
   100                 return;
       
   101             }
       
   102             if (value instanceof Float) {
       
   103                 Float fValue = (Float) value;
       
   104                 if (Float.isNaN(fValue) || Float.isInfinite(fValue)) {
       
   105                     printNull();
       
   106                     return;
       
   107                 }
       
   108                 printAsString(value);
       
   109                 return;
       
   110             }
       
   111             if (value instanceof Number) {
       
   112                 printAsString(value);
       
   113                 return;
       
   114             }
       
   115             print("\"");
       
   116             printEscaped(String.valueOf(value));
       
   117             print("\"");
       
   118         }
       
   119     }
       
   120 
       
   121     public void printObject(RecordedObject object) {
       
   122         printObjectBegin();
       
   123         boolean first = true;
       
   124         for (ValueDescriptor v : object.getFields()) {
       
   125             printValueDescriptor(first, false, v, object.getValue(v.getName()));
       
   126             first = false;
       
   127         }
       
   128         printObjectEnd();
       
   129     }
       
   130 
       
   131     private void printArray(ValueDescriptor v, Object[] array) {
       
   132         printArrayBegin();
       
   133         boolean first = true;
       
   134         for (Object arrayElement : array) {
       
   135             printValueDescriptor(first, true, v, arrayElement);
       
   136             first = false;
       
   137         }
       
   138         printArrayEnd();
       
   139     }
       
   140 
       
   141     private void printValueDescriptor(boolean first, boolean arrayElement, ValueDescriptor vd, Object value) {
       
   142         if (vd.isArray() && !arrayElement) {
       
   143             printNewDataStructure(first, arrayElement, vd.getName());
       
   144             if (!printIfNull(value)) {
       
   145                 printArray(vd, (Object[]) value);
       
   146             }
       
   147             return;
       
   148         }
       
   149         if (!vd.getFields().isEmpty()) {
       
   150             printNewDataStructure(first, arrayElement, vd.getName());
       
   151             if (!printIfNull(value)) {
       
   152                 printObject((RecordedObject) value);
       
   153             }
       
   154             return;
       
   155         }
       
   156         printValue(first, arrayElement, vd.getName(), value);
       
   157     }
       
   158 
       
   159     private void printNewDataStructure(boolean first, boolean arrayElement, String name) {
       
   160         if (!first) {
       
   161             print(", ");
       
   162             if (!arrayElement) {
       
   163                 println();
       
   164             }
       
   165         }
       
   166         if (!arrayElement) {
       
   167             printDataStructureName(name);
       
   168         }
       
   169     }
       
   170 
       
   171     private boolean printIfNull(Object value) {
       
   172         if (value == null) {
       
   173             printNull();
       
   174             return true;
       
   175         }
       
   176         return false;
       
   177     }
       
   178 
       
   179     private void printNull() {
       
   180         print("null");
       
   181     }
       
   182 
       
   183     private void printDataStructureName(String text) {
       
   184         printIndent();
       
   185         print("\"");
       
   186         print(text);
       
   187         print("\": ");
       
   188     }
       
   189 
       
   190     private void printObjectEnd() {
       
   191         retract();
       
   192         println();
       
   193         printIndent();
       
   194         print("}");
       
   195     }
       
   196 
       
   197     private void printObjectBegin() {
       
   198         println("{");
       
   199         indent();
       
   200     }
       
   201 
       
   202     private void printArrayEnd() {
       
   203         print("]");
       
   204     }
       
   205 
       
   206     private void printArrayBegin() {
       
   207         print("[");
       
   208     }
       
   209 
       
   210     private void printEscaped(String text) {
       
   211         for (int i = 0; i < text.length(); i++) {
       
   212             printEscaped(text.charAt(i));
       
   213         }
       
   214     }
       
   215 
       
   216     private void printEscaped(char c) {
       
   217         if (c == '\b') {
       
   218             print("\\b");
       
   219             return;
       
   220         }
       
   221         if (c == '\n') {
       
   222             print("\\n");
       
   223             return;
       
   224         }
       
   225         if (c == '\t') {
       
   226             print("\\t");
       
   227             return;
       
   228         }
       
   229         if (c == '\f') {
       
   230             print("\\f");
       
   231             return;
       
   232         }
       
   233         if (c == '\r') {
       
   234             print("\\r");
       
   235             return;
       
   236         }
       
   237         if (c == '\"') {
       
   238             print("\\\"");
       
   239             return;
       
   240         }
       
   241         if (c == '\\') {
       
   242             print("\\\\");
       
   243             return;
       
   244         }
       
   245         if (c == '/') {
       
   246             print("\\/");
       
   247             return;
       
   248         }
       
   249         if (c > 0x7F || c < 32) {
       
   250             print("\\u");
       
   251             // 0x10000 will pad with zeros.
       
   252             print(Integer.toHexString(0x10000 + (int) c).substring(1));
       
   253             return;
       
   254         }
       
   255         print(c);
       
   256     }
       
   257 
       
   258 }