1/* 2 * Copyright (c) 2008, 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24package com.sun.hotspot.igv.data.serialization; 25 26import com.sun.hotspot.igv.data.*; 27import java.io.IOException; 28import java.io.InputStream; 29import java.io.Writer; 30import java.util.HashSet; 31import java.util.Set; 32 33/** 34 * 35 * @author Thomas Wuerthinger 36 */ 37public class Printer { 38 39 private InputStream in; 40 41 public Printer() { 42 this(null); 43 } 44 45 public Printer(InputStream inputStream) { 46 this.in = inputStream; 47 } 48 49 public void export(Writer writer, GraphDocument document) { 50 51 XMLWriter xmlWriter = new XMLWriter(writer); 52 53 try { 54 export(xmlWriter, document); 55 } catch (IOException ex) { 56 } 57 } 58 59 private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException { 60 xmlWriter.startTag(Parser.ROOT_ELEMENT); 61 xmlWriter.writeProperties(document.getProperties()); 62 for (FolderElement e : document.getElements()) { 63 if (e instanceof Group) { 64 export(xmlWriter, (Group) e); 65 } else if (e instanceof InputGraph) { 66 export(xmlWriter, (InputGraph)e, null, false); 67 } 68 } 69 70 xmlWriter.endTag(); 71 xmlWriter.flush(); 72 } 73 74 private void export(XMLWriter writer, Group g) throws IOException { 75 Properties attributes = new Properties(); 76 attributes.setProperty("difference", Boolean.toString(true)); 77 writer.startTag(Parser.GROUP_ELEMENT, attributes); 78 writer.writeProperties(g.getProperties()); 79 80 boolean shouldExport = true; 81 if (in != null) { 82 char c = (char) in.read(); 83 if (c != 'y') { 84 shouldExport = false; 85 } 86 } 87 88 if (shouldExport) { 89 if (g.getMethod() != null) { 90 export(writer, g.getMethod()); 91 } 92 93 InputGraph previous = null; 94 for (FolderElement e : g.getElements()) { 95 if (e instanceof InputGraph) { 96 InputGraph graph = (InputGraph) e; 97 export(writer, graph, previous, true); 98 previous = graph; 99 } else if (e instanceof Group) { 100 export(writer, (Group) e); 101 } 102 } 103 } 104 105 writer.endTag(); 106 } 107 108 public void export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference) throws IOException { 109 110 writer.startTag(Parser.GRAPH_ELEMENT); 111 writer.writeProperties(graph.getProperties()); 112 writer.startTag(Parser.NODES_ELEMENT); 113 114 Set<InputNode> removed = new HashSet<>(); 115 Set<InputNode> equal = new HashSet<>(); 116 117 if (previous != null) { 118 for (InputNode n : previous.getNodes()) { 119 int id = n.getId(); 120 InputNode n2 = graph.getNode(id); 121 if (n2 == null) { 122 removed.add(n); 123 } else if (n.equals(n2)) { 124 equal.add(n); 125 } 126 } 127 } 128 129 if (difference) { 130 for (InputNode n : removed) { 131 writer.simpleTag(Parser.REMOVE_NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); 132 } 133 } 134 135 for (InputNode n : graph.getNodes()) { 136 if (!difference || !equal.contains(n)) { 137 writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); 138 writer.writeProperties(n.getProperties()); 139 writer.endTag(); 140 } 141 } 142 143 writer.endTag(); 144 145 writer.startTag(Parser.EDGES_ELEMENT); 146 Set<InputEdge> removedEdges = new HashSet<>(); 147 Set<InputEdge> equalEdges = new HashSet<>(); 148 149 if (previous != null) { 150 for (InputEdge e : previous.getEdges()) { 151 if (graph.getEdges().contains(e)) { 152 equalEdges.add(e); 153 } else { 154 removedEdges.add(e); 155 } 156 } 157 } 158 159 if (difference) { 160 for (InputEdge e : removedEdges) { 161 writer.simpleTag(Parser.REMOVE_EDGE_ELEMENT, createProperties(e)); 162 } 163 } 164 165 for (InputEdge e : graph.getEdges()) { 166 if (!difference || !equalEdges.contains(e)) { 167 if (!equalEdges.contains(e)) { 168 writer.simpleTag(Parser.EDGE_ELEMENT, createProperties(e)); 169 } 170 } 171 } 172 173 writer.endTag(); 174 175 writer.startTag(Parser.CONTROL_FLOW_ELEMENT); 176 for (InputBlock b : graph.getBlocks()) { 177 writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName())); 178 179 if (b.getSuccessors().size() > 0) { 180 writer.startTag(Parser.SUCCESSORS_ELEMENT); 181 for (InputBlock s : b.getSuccessors()) { 182 writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName())); 183 } 184 writer.endTag(); 185 } 186 187 if (b.getNodes().size() > 0) { 188 writer.startTag(Parser.NODES_ELEMENT); 189 for (InputNode n : b.getNodes()) { 190 writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + "")); 191 } 192 writer.endTag(); 193 } 194 195 writer.endTag(); 196 } 197 198 writer.endTag(); 199 writer.endTag(); 200 } 201 202 private void export(XMLWriter w, InputMethod method) throws IOException { 203 204 w.startTag(Parser.METHOD_ELEMENT, new Properties(Parser.METHOD_BCI_PROPERTY, method.getBci() + "", Parser.METHOD_NAME_PROPERTY, method.getName(), Parser.METHOD_SHORT_NAME_PROPERTY, method.getShortName())); 205 206 w.writeProperties(method.getProperties()); 207 208 if (method.getInlined().size() > 0) { 209 w.startTag(Parser.INLINE_ELEMENT); 210 for (InputMethod m : method.getInlined()) { 211 export(w, m); 212 } 213 w.endTag(); 214 } 215 216 w.startTag(Parser.BYTECODES_ELEMENT); 217 218 StringBuilder b = new StringBuilder(); 219 b.append("<![CDATA[\n"); 220 for (InputBytecode code : method.getBytecodes()) { 221 b.append(code.getBci()); 222 b.append(" "); 223 b.append(code.getName()); 224 b.append("\n"); 225 } 226 227 b.append("]]>"); 228 w.write(b.toString()); 229 w.endTag(); 230 w.endTag(); 231 } 232 233 private Properties createProperties(InputEdge edge) { 234 Properties p = new Properties(); 235 if (edge.getToIndex() != 0) { 236 p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex())); 237 } 238 if (edge.getFromIndex() != 0) { 239 p.setProperty(Parser.FROM_INDEX_PROPERTY, Integer.toString(edge.getFromIndex())); 240 } 241 p.setProperty(Parser.TO_PROPERTY, Integer.toString(edge.getTo())); 242 p.setProperty(Parser.FROM_PROPERTY, Integer.toString(edge.getFrom())); 243 p.setProperty(Parser.TYPE_PROPERTY, edge.getType()); 244 return p; 245 } 246} 247