Parser.java revision 1472:c18cbe5936b8
1/* 2 * Copyright (c) 2008, 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.GraphDocument; 27import com.sun.hotspot.igv.data.Group; 28import com.sun.hotspot.igv.data.InputBlock; 29import com.sun.hotspot.igv.data.InputEdge; 30import com.sun.hotspot.igv.data.InputGraph; 31import com.sun.hotspot.igv.data.InputMethod; 32import com.sun.hotspot.igv.data.InputNode; 33import com.sun.hotspot.igv.data.Properties; 34import com.sun.hotspot.igv.data.Property; 35import com.sun.hotspot.igv.data.services.GroupCallback; 36import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler; 37import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler; 38import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor; 39import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler; 40import java.io.IOException; 41import java.util.HashMap; 42import org.xml.sax.InputSource; 43import org.xml.sax.SAXException; 44import org.xml.sax.XMLReader; 45 46/** 47 * 48 * @author Thomas Wuerthinger 49 */ 50public class Parser { 51 52 public static final String INDENT = " "; 53 public static final String TOP_ELEMENT = "graphDocument"; 54 public static final String GROUP_ELEMENT = "group"; 55 public static final String GRAPH_ELEMENT = "graph"; 56 public static final String ROOT_ELEMENT = "graphDocument"; 57 public static final String PROPERTIES_ELEMENT = "properties"; 58 public static final String EDGES_ELEMENT = "edges"; 59 public static final String PROPERTY_ELEMENT = "p"; 60 public static final String EDGE_ELEMENT = "edge"; 61 public static final String NODE_ELEMENT = "node"; 62 public static final String NODES_ELEMENT = "nodes"; 63 public static final String REMOVE_EDGE_ELEMENT = "removeEdge"; 64 public static final String REMOVE_NODE_ELEMENT = "removeNode"; 65 public static final String METHOD_NAME_PROPERTY = "name"; 66 public static final String METHOD_IS_PUBLIC_PROPERTY = "public"; 67 public static final String METHOD_IS_STATIC_PROPERTY = "static"; 68 public static final String TRUE_VALUE = "true"; 69 public static final String NODE_NAME_PROPERTY = "name"; 70 public static final String EDGE_NAME_PROPERTY = "name"; 71 public static final String NODE_ID_PROPERTY = "id"; 72 public static final String FROM_PROPERTY = "from"; 73 public static final String TO_PROPERTY = "to"; 74 public static final String PROPERTY_NAME_PROPERTY = "name"; 75 public static final String GRAPH_NAME_PROPERTY = "name"; 76 public static final String TO_INDEX_PROPERTY = "index"; 77 public static final String METHOD_ELEMENT = "method"; 78 public static final String INLINE_ELEMENT = "inline"; 79 public static final String BYTECODES_ELEMENT = "bytecodes"; 80 public static final String METHOD_BCI_PROPERTY = "bci"; 81 public static final String METHOD_SHORT_NAME_PROPERTY = "shortName"; 82 public static final String CONTROL_FLOW_ELEMENT = "controlFlow"; 83 public static final String BLOCK_NAME_PROPERTY = "name"; 84 public static final String BLOCK_ELEMENT = "block"; 85 public static final String SUCCESSORS_ELEMENT = "successors"; 86 public static final String SUCCESSOR_ELEMENT = "successor"; 87 public static final String ASSEMBLY_ELEMENT = "assembly"; 88 public static final String DIFFERENCE_PROPERTY = "difference"; 89 private TopElementHandler xmlDocument = new TopElementHandler(); 90 private boolean difference; 91 private GroupCallback groupCallback; 92 private HashMap<String, Integer> idCache = new HashMap<String, Integer>(); 93 private int maxId = 0; 94 95 private int lookupID(String i) { 96 Integer id = idCache.get(i); 97 if (id == null) { 98 id = maxId++; 99 idCache.put(i, id); 100 } 101 return id.intValue(); 102 } 103 104 // <graphDocument> 105 private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) { 106 107 @Override 108 protected GraphDocument start() throws SAXException { 109 return new GraphDocument(); 110 } 111 }; 112 // <group> 113 private ElementHandler<Group, GraphDocument> groupHandler = new XMLParser.ElementHandler<Group, GraphDocument>(GROUP_ELEMENT) { 114 115 @Override 116 protected Group start() throws SAXException { 117 Group group = new Group(); 118 Parser.this.difference = false; 119 String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY); 120 if (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))) { 121 Parser.this.difference = true; 122 } 123 124 ParseMonitor monitor = getMonitor(); 125 if (monitor != null) { 126 monitor.setState(group.getName()); 127 } 128 129 return group; 130 } 131 132 @Override 133 protected void end(String text) throws SAXException { 134 if (groupCallback == null) { 135 getParentObject().addGroup(getObject()); 136 } 137 } 138 }; 139 private HandoverElementHandler<Group> assemblyHandler = new XMLParser.HandoverElementHandler<Group>(ASSEMBLY_ELEMENT, true) { 140 141 @Override 142 protected void end(String text) throws SAXException { 143 getParentObject().setAssembly(text); 144 } 145 }; 146 // <method> 147 private ElementHandler<InputMethod, Group> methodHandler = new XMLParser.ElementHandler<InputMethod, Group>(METHOD_ELEMENT) { 148 149 @Override 150 protected InputMethod start() throws SAXException { 151 152 InputMethod method = parseMethod(this, getParentObject()); 153 getParentObject().setMethod(method); 154 return method; 155 } 156 }; 157 158 private InputMethod parseMethod(XMLParser.ElementHandler handler, Group group) throws SAXException { 159 String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY); 160 int bci = 0; 161 try { 162 bci = Integer.parseInt(s); 163 } catch (NumberFormatException e) { 164 throw new SAXException(e); 165 } 166 InputMethod method = new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci); 167 return method; 168 } 169 // <bytecodes> 170 private HandoverElementHandler<InputMethod> bytecodesHandler = new XMLParser.HandoverElementHandler<InputMethod>(BYTECODES_ELEMENT, true) { 171 172 @Override 173 protected void end(String text) throws SAXException { 174 getParentObject().setBytecodes(text); 175 } 176 }; 177 // <inlined> 178 private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<InputMethod>(INLINE_ELEMENT); 179 // <inlined><method> 180 private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) { 181 182 @Override 183 protected InputMethod start() throws SAXException { 184 InputMethod method = parseMethod(this, getParentObject().getGroup()); 185 getParentObject().addInlined(method); 186 return method; 187 } 188 }; 189 // <graph> 190 private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) { 191 192 private InputGraph graph; 193 194 @Override 195 protected InputGraph start() throws SAXException { 196 197 String name = readAttribute(GRAPH_NAME_PROPERTY); 198 InputGraph previous = getParentObject().getLastAdded(); 199 if (!difference) { 200 previous = null; 201 } 202 InputGraph curGraph = new InputGraph(getParentObject(), previous, name); 203 this.graph = curGraph; 204 return curGraph; 205 } 206 207 @Override 208 protected void end(String text) throws SAXException { 209 getParentObject().addGraph(graph); 210 graph.resolveBlockLinks(); 211 } 212 }; 213 // <nodes> 214 private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<InputGraph>(NODES_ELEMENT); 215 // <controlFlow> 216 private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<InputGraph>(CONTROL_FLOW_ELEMENT); 217 // <block> 218 private ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<InputBlock, InputGraph>(BLOCK_ELEMENT) { 219 220 @Override 221 protected InputBlock start() throws SAXException { 222 InputGraph graph = getParentObject(); 223 String name = readRequiredAttribute(BLOCK_NAME_PROPERTY).intern(); 224 InputBlock b = new InputBlock(getParentObject(), name); 225 graph.addBlock(b); 226 return b; 227 } 228 }; 229 // <nodes> 230 private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<InputBlock>(NODES_ELEMENT); 231 // <node> 232 private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) { 233 234 @Override 235 protected InputBlock start() throws SAXException { 236 String s = readRequiredAttribute(NODE_ID_PROPERTY); 237 238 int id = 0; 239 try { 240 id = lookupID(s); 241 } catch (NumberFormatException e) { 242 throw new SAXException(e); 243 } 244 getParentObject().addNode(id); 245 return getParentObject(); 246 } 247 }; 248 // <successors> 249 private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<InputBlock>(SUCCESSORS_ELEMENT); 250 // <successor> 251 private ElementHandler<InputBlock, InputBlock> successorHandler = new ElementHandler<InputBlock, InputBlock>(SUCCESSOR_ELEMENT) { 252 253 @Override 254 protected InputBlock start() throws SAXException { 255 String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); 256 getParentObject().addSuccessor(name); 257 return getParentObject(); 258 } 259 }; 260 // <node> 261 private ElementHandler<InputNode, InputGraph> nodeHandler = new ElementHandler<InputNode, InputGraph>(NODE_ELEMENT) { 262 263 @Override 264 protected InputNode start() throws SAXException { 265 String s = readRequiredAttribute(NODE_ID_PROPERTY); 266 int id = 0; 267 try { 268 id = lookupID(s); 269 } catch (NumberFormatException e) { 270 throw new SAXException(e); 271 } 272 InputNode node = new InputNode(id); 273 getParentObject().addNode(node); 274 return node; 275 } 276 }; 277 // <removeNode> 278 private ElementHandler<InputNode, InputGraph> removeNodeHandler = new ElementHandler<InputNode, InputGraph>(REMOVE_NODE_ELEMENT) { 279 280 @Override 281 protected InputNode start() throws SAXException { 282 String s = readRequiredAttribute(NODE_ID_PROPERTY); 283 int id = 0; 284 try { 285 id = lookupID(s); 286 } catch (NumberFormatException e) { 287 throw new SAXException(e); 288 } 289 return getParentObject().removeNode(id); 290 } 291 }; 292 // <graph> 293 private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<InputGraph>(EDGES_ELEMENT); 294 295 // Local class for edge elements 296 private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> { 297 298 public EdgeElementHandler(String name) { 299 super(name); 300 } 301 302 @Override 303 protected InputEdge start() throws SAXException { 304 int toIndex = 0; 305 int from = -1; 306 int to = -1; 307 308 try { 309 String toIndexString = readAttribute(TO_INDEX_PROPERTY); 310 if (toIndexString != null) { 311 toIndex = Integer.parseInt(toIndexString); 312 } 313 314 from = lookupID(readRequiredAttribute(FROM_PROPERTY)); 315 to = lookupID(readRequiredAttribute(TO_PROPERTY)); 316 } catch (NumberFormatException e) { 317 throw new SAXException(e); 318 } 319 320 321 InputEdge conn = new InputEdge((char) toIndex, from, to); 322 return start(conn); 323 } 324 325 protected InputEdge start(InputEdge conn) throws SAXException { 326 return conn; 327 } 328 } 329 // <edge> 330 private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) { 331 332 @Override 333 protected InputEdge start(InputEdge conn) throws SAXException { 334 getParentObject().addEdge(conn); 335 return conn; 336 } 337 }; 338 // <removeEdge> 339 private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) { 340 341 @Override 342 protected InputEdge start(InputEdge conn) throws SAXException { 343 getParentObject().removeEdge(conn); 344 return conn; 345 } 346 }; 347 // <properties> 348 private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<Properties.Provider>(PROPERTIES_ELEMENT); 349 // <properties> 350 private HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<Group>(PROPERTIES_ELEMENT) { 351 352 @Override 353 public void end(String text) throws SAXException { 354 if (groupCallback != null) { 355 groupCallback.started(getParentObject()); 356 } 357 } 358 }; 359 // <property> 360 private ElementHandler<String, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<String, Properties.Provider>(PROPERTY_ELEMENT, true) { 361 362 @Override 363 public String start() throws SAXException { 364 return readRequiredAttribute(PROPERTY_NAME_PROPERTY).intern(); 365 } 366 367 @Override 368 public void end(String text) { 369 getParentObject().getProperties().setProperty(getObject(), text.trim().intern()); 370 } 371 }; 372 373 public Parser() { 374 this(null); 375 } 376 377 public Parser(GroupCallback groupCallback) { 378 379 this.groupCallback = groupCallback; 380 381 // Initialize dependencies 382 xmlDocument.addChild(topHandler); 383 topHandler.addChild(groupHandler); 384 385 groupHandler.addChild(methodHandler); 386 groupHandler.addChild(assemblyHandler); 387 groupHandler.addChild(graphHandler); 388 389 methodHandler.addChild(inlinedHandler); 390 methodHandler.addChild(bytecodesHandler); 391 392 inlinedHandler.addChild(inlinedMethodHandler); 393 inlinedMethodHandler.addChild(bytecodesHandler); 394 inlinedMethodHandler.addChild(inlinedHandler); 395 396 graphHandler.addChild(nodesHandler); 397 graphHandler.addChild(edgesHandler); 398 graphHandler.addChild(controlFlowHandler); 399 400 controlFlowHandler.addChild(blockHandler); 401 402 blockHandler.addChild(successorsHandler); 403 successorsHandler.addChild(successorHandler); 404 blockHandler.addChild(blockNodesHandler); 405 blockNodesHandler.addChild(blockNodeHandler); 406 407 nodesHandler.addChild(nodeHandler); 408 nodesHandler.addChild(removeNodeHandler); 409 edgesHandler.addChild(edgeHandler); 410 edgesHandler.addChild(removeEdgeHandler); 411 412 methodHandler.addChild(propertiesHandler); 413 inlinedMethodHandler.addChild(propertiesHandler); 414 topHandler.addChild(propertiesHandler); 415 groupHandler.addChild(groupPropertiesHandler); 416 graphHandler.addChild(propertiesHandler); 417 nodeHandler.addChild(propertiesHandler); 418 propertiesHandler.addChild(propertyHandler); 419 groupPropertiesHandler.addChild(propertyHandler); 420 } 421 422 // Returns a new GraphDocument object deserialized from an XML input source. 423 public GraphDocument parse(XMLReader reader, InputSource source, XMLParser.ParseMonitor monitor) throws SAXException { 424 reader.setContentHandler(new XMLParser(xmlDocument, monitor)); 425 try { 426 reader.parse(source); 427 } catch (IOException ex) { 428 throw new SAXException(ex); 429 } 430 431 return topHandler.getObject(); 432 } 433} 434