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