| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package jdk.jfr.internal.tool;  | 
 | 
 | 
 | 
import java.io.PrintWriter;  | 
 | 
import java.util.List;  | 
 | 
 | 
 | 
import jdk.jfr.EventType;  | 
 | 
import jdk.jfr.ValueDescriptor;  | 
 | 
import jdk.jfr.consumer.RecordedEvent;  | 
 | 
import jdk.jfr.consumer.RecordedFrame;  | 
 | 
import jdk.jfr.consumer.RecordedObject;  | 
 | 
 | 
 | 
final class XMLWriter extends EventPrintWriter { | 
 | 
    public XMLWriter(PrintWriter destination) { | 
 | 
        super(destination);  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected void printBegin() { | 
 | 
        println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); | 
 | 
        println("<recording xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"); | 
 | 
        indent();  | 
 | 
        printIndent();  | 
 | 
        println("<events>"); | 
 | 
        indent();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected void printEnd() { | 
 | 
        retract();  | 
 | 
        printIndent();  | 
 | 
        println("</events>"); | 
 | 
        retract();  | 
 | 
        println("</recording>"); | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected void print(List<RecordedEvent> events) { | 
 | 
        for (RecordedEvent event : events) { | 
 | 
            printEvent(event);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void printEvent(RecordedEvent event) { | 
 | 
        EventType type = event.getEventType();  | 
 | 
        printIndent();  | 
 | 
        print("<event"); | 
 | 
        printAttribute("type", type.getName()); | 
 | 
        print(">"); | 
 | 
        println();  | 
 | 
        indent();  | 
 | 
        for (ValueDescriptor v : event.getFields()) { | 
 | 
            printValueDescriptor(v, getValue(event, v), -1);  | 
 | 
        }  | 
 | 
        retract();  | 
 | 
        printIndent();  | 
 | 
        println("</event>"); | 
 | 
        println();  | 
 | 
    }  | 
 | 
 | 
 | 
    private void printAttribute(String name, String value) { | 
 | 
        print(" ", name, "=\"", value, "\""); | 
 | 
    }  | 
 | 
 | 
 | 
    public void printObject(RecordedObject struct) { | 
 | 
        println();  | 
 | 
        indent();  | 
 | 
        for (ValueDescriptor v : struct.getFields()) { | 
 | 
            printValueDescriptor(v, getValue(struct, v), -1);  | 
 | 
        }  | 
 | 
        retract();  | 
 | 
    }  | 
 | 
 | 
 | 
    private void printArray(ValueDescriptor v, Object[] array) { | 
 | 
        println();  | 
 | 
        indent();  | 
 | 
        int depth = 0;  | 
 | 
        for (int index = 0; index < array.length; index++) { | 
 | 
            Object arrayElement = array[index];  | 
 | 
            if (!(arrayElement instanceof RecordedFrame) || depth < getStackDepth()) { | 
 | 
                printValueDescriptor(v, array[index], index);  | 
 | 
            }  | 
 | 
            depth++;  | 
 | 
        }  | 
 | 
        retract();  | 
 | 
    }  | 
 | 
 | 
 | 
    private void printValueDescriptor(ValueDescriptor vd, Object value, int index) { | 
 | 
        boolean arrayElement = index != -1;  | 
 | 
        String name = arrayElement ? null : vd.getName();  | 
 | 
        if (vd.isArray() && !arrayElement) { | 
 | 
            if (printBeginElement("array", name, value, index)) { | 
 | 
                printArray(vd, (Object[]) value);  | 
 | 
                printIndent();  | 
 | 
                printEndElement("array"); | 
 | 
            }  | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (!vd.getFields().isEmpty()) { | 
 | 
            if (printBeginElement("struct", name, value, index)) { | 
 | 
                printObject((RecordedObject) value);  | 
 | 
                printIndent();  | 
 | 
                printEndElement("struct"); | 
 | 
            }  | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (printBeginElement("value", name, value, index)) { | 
 | 
            printEscaped(String.valueOf(value));  | 
 | 
            printEndElement("value"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private boolean printBeginElement(String elementName, String name, Object value, int index) { | 
 | 
        printIndent();  | 
 | 
        print("<", elementName); | 
 | 
        if (name != null) { | 
 | 
            printAttribute("name", name); | 
 | 
        }  | 
 | 
        if (index != -1) { | 
 | 
            printAttribute("index", Integer.toString(index)); | 
 | 
        }  | 
 | 
        if (value == null) { | 
 | 
            printAttribute("xsi:nil", "true"); | 
 | 
            println("/>"); | 
 | 
            return false;  | 
 | 
        }  | 
 | 
        if (value.getClass().isArray()) { | 
 | 
            Object[] array = (Object[]) value;  | 
 | 
            printAttribute("size", Integer.toString(array.length)); | 
 | 
        }  | 
 | 
        print(">"); | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
    private void printEndElement(String elementName) { | 
 | 
        print("</"); | 
 | 
        print(elementName);  | 
 | 
        println(">"); | 
 | 
    }  | 
 | 
 | 
 | 
    private void printEscaped(String text) { | 
 | 
        for (int i = 0; i < text.length(); i++) { | 
 | 
            printEscaped(text.charAt(i));  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void printEscaped(char c) { | 
 | 
        if (c == 34) { | 
 | 
            print("""); | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (c == 38) { | 
 | 
            print("&"); | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (c == 39) { | 
 | 
            print("'"); | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (c == 60) { | 
 | 
            print("<"); | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (c == 62) { | 
 | 
            print(">"); | 
 | 
            return;  | 
 | 
        }  | 
 | 
        if (c > 0x7F) { | 
 | 
            print("&#"); | 
 | 
            print((int) c);  | 
 | 
            print(';'); | 
 | 
            return;  | 
 | 
        }  | 
 | 
        print(c);  | 
 | 
    }  | 
 | 
}  |