|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
XPathLocationParser | Line # 60 | 155 | 51 | 82.3% |
0.8229665
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
(65) | |||
Result | |||
0.67942584
|
org.qedeq.kernel.bo.service.logic.FormalProofCheckerPluginTest.testPlugin3 org.qedeq.kernel.bo.service.logic.FormalProofCheckerPluginTest.testPlugin3 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq5 org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq5 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testGeneration2 org.qedeq.kernel.bo.latex.GenerateLatexTest.testGeneration2 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testGeneration org.qedeq.kernel.bo.latex.GenerateLatexTest.testGeneration | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq4 org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq4 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.module.VisitorContextTest.testContext org.qedeq.kernel.bo.module.VisitorContextTest.testContext | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq3 org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq3 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq6 org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq6 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq1 org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq1 | 1 PASS | |
0.6602871
|
org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq2 org.qedeq.kernel.bo.service.control.QedeqBoFactoryTest.testCreateStringQedeq2 | 1 PASS | |
0.6555024
|
org.qedeq.kernel.xml.tracker.XPathLocationFinderTest.testGetXPathLocation org.qedeq.kernel.xml.tracker.XPathLocationFinderTest.testGetXPathLocation | 1 PASS | |
0.6555024
|
org.qedeq.kernel.xml.tracker.XPathLocationParserTest.testGetXPathLocation org.qedeq.kernel.xml.tracker.XPathLocationParserTest.testGetXPathLocation | 1 PASS | |
0.6507177
|
org.qedeq.kernel.bo.service.logic.FormalProofCheckerPluginTest.testPlugin2 org.qedeq.kernel.bo.service.logic.FormalProofCheckerPluginTest.testPlugin2 | 1 PASS | |
0.6507177
|
org.qedeq.kernel.bo.service.heuristic.HeuristicCheckerPluginTest.testQedeqSetTheoryScript1 org.qedeq.kernel.bo.service.heuristic.HeuristicCheckerPluginTest.testQedeqSetTheoryScript1 | 1 PASS | |
0.6363636
|
org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L001_v2 org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L001_v2 | 1 PASS | |
0.6363636
|
org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L001_v1 org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L001_v1 | 1 PASS | |
0.6363636
|
org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerTest.testCheckModule org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerTest.testCheckModule | 1 PASS | |
0.58373207
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_11 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_11 | 1 PASS | |
0.58373207
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegativeGeneration2 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegativeGeneration2 | 1 PASS | |
0.58373207
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegativeGeneration2 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegativeGeneration2 | 1 PASS | |
0.58373207
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testGeneration2 org.qedeq.kernel.bo.latex.GenerateLatexTest.testGeneration2 | 1 PASS | |
0.58373207
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_08 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_08 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_02 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_02 | 1 PASS | |
0.569378
|
org.qedeq.kernel.xml.parser.CharsetParserTest.testParse1 org.qedeq.kernel.xml.parser.CharsetParserTest.testParse1 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_03 org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_03 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative06 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative06 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_04 org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_04 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_02 org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_02 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_10 org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_10 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_09 org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_09 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative06 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative06 | 1 PASS | |
0.569378
|
org.qedeq.kernel.xml.parser.CharsetParserTest.testParse2 org.qedeq.kernel.xml.parser.CharsetParserTest.testParse2 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_07 org.qedeq.kernel.bo.service.control.LoadRequiredModulesTest.testLoadRequiredModules_07 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_12 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_12 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_07 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_07 | 1 PASS | |
0.569378
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_03 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_03 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration6 org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration6 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerDirectTest.testNegative04 org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerDirectTest.testNegative04 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_10 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_10 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.logic.wf.FormulaCheckerContextTest.testNegative04 org.qedeq.kernel.bo.logic.wf.FormulaCheckerContextTest.testNegative04 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerDirectTest.testNegative02 org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerDirectTest.testNegative02 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative02 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative02 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.heuristic.HeuristicCheckerPluginTest.testQedeqSetTheoryScript2 org.qedeq.kernel.bo.service.heuristic.HeuristicCheckerPluginTest.testQedeqSetTheoryScript2 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative08 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative08 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.logic.wf.FormulaCheckerContextTest.testNegative02 org.qedeq.kernel.bo.logic.wf.FormulaCheckerContextTest.testNegative02 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L003 org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L003 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration1 org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration1 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration5 org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration5 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative05 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative05 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.logic.SimpleProofFinderPluginTest.testPlugin org.qedeq.kernel.bo.service.logic.SimpleProofFinderPluginTest.testPlugin | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration2 org.qedeq.kernel.bo.service.unicode.GenerateUtf8Test.testGeneration2 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.logic.SimpleProofFinderPluginTest.testPlugin2 org.qedeq.kernel.bo.service.logic.SimpleProofFinderPluginTest.testPlugin2 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_09 org.qedeq.kernel.bo.service.control.ModuleConstantsExistenceCheckerTest.testModuleConstantsExistenceChecker_09 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative02 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative02 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative08 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative08 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.logic.SimpleProofFinderPluginTest.testPluginFast org.qedeq.kernel.bo.service.logic.SimpleProofFinderPluginTest.testPluginFast | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerDirectTest.testNegative03 org.qedeq.kernel.bo.service.logic.QedeqBoFormalLogicCheckerDirectTest.testNegative03 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative05 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative05 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.xml.dao.GenerateXmlTest.testGeneration org.qedeq.kernel.xml.dao.GenerateXmlTest.testGeneration | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative07 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative07 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative07 org.qedeq.kernel.bo.latex.GenerateLatexTest.testNegative07 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L002 org.qedeq.kernel.bo.service.latex.Qedeq2LatexTest.testQ2L002 | 1 PASS | |
0.5598086
|
org.qedeq.kernel.bo.logic.wf.FormulaCheckerContextTest.testNegative03 org.qedeq.kernel.bo.logic.wf.FormulaCheckerContextTest.testNegative03 | 1 PASS | |
0.43540668
|
org.qedeq.kernel.xml.tracker.XPathLocationFinderTest.testTagNotFound org.qedeq.kernel.xml.tracker.XPathLocationFinderTest.testTagNotFound | 1 PASS | |
0.19138756
|
org.qedeq.kernel.xml.tracker.XPathLocationFinderTest.testFileNotOk org.qedeq.kernel.xml.tracker.XPathLocationFinderTest.testFileNotOk | 1 PASS | |
1 | /* This file is part of the project "Hilbert II" - http://www.qedeq.org | |
2 | * | |
3 | * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>. | |
4 | * | |
5 | * "Hilbert II" is free software; you can redistribute | |
6 | * it and/or modify it under the terms of the GNU General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | */ | |
15 | package org.qedeq.kernel.xml.tracker; | |
16 | ||
17 | import java.io.File; | |
18 | import java.io.FileInputStream; | |
19 | import java.io.IOException; | |
20 | import java.io.InputStream; | |
21 | import java.io.Reader; | |
22 | import java.util.ArrayList; | |
23 | import java.util.HashMap; | |
24 | import java.util.List; | |
25 | import java.util.Map; | |
26 | ||
27 | import javax.xml.parsers.ParserConfigurationException; | |
28 | import javax.xml.parsers.SAXParser; | |
29 | import javax.xml.parsers.SAXParserFactory; | |
30 | ||
31 | import org.qedeq.base.io.IoUtility; | |
32 | import org.qedeq.base.io.SourceArea; | |
33 | import org.qedeq.base.io.SourcePosition; | |
34 | import org.qedeq.base.io.TextInput; | |
35 | import org.qedeq.base.trace.Trace; | |
36 | import org.qedeq.base.utility.Enumerator; | |
37 | import org.qedeq.kernel.xml.handler.common.SimpleHandler; | |
38 | import org.xml.sax.Attributes; | |
39 | import org.xml.sax.InputSource; | |
40 | import org.xml.sax.SAXException; | |
41 | import org.xml.sax.XMLReader; | |
42 | ||
43 | import com.sun.syndication.io.XmlReader; | |
44 | ||
45 | /** | |
46 | * Parser for XML files. Search simple XPath within an XML file. | |
47 | * Usage: | |
48 | * <pre> | |
49 | * final XPathLocationParser parser = new XPathLocationParser(xpath); | |
50 | * parser.parse(xmlFile, original); | |
51 | * return parser.getFind(); | |
52 | * | |
53 | * </pre> | |
54 | * | |
55 | * If the system property "qedeq.test.xmlLocationFailures" is set to "true" a runtime | |
56 | * exception is thrown if the path is not found. | |
57 | * | |
58 | * @author Michael Meyling | |
59 | */ | |
60 | public final class XPathLocationParser extends SimpleHandler { | |
61 | ||
62 | /** This class. */ | |
63 | private static final Class CLASS = XPathLocationParser.class; | |
64 | ||
65 | /** Namespaces feature id (http://xml.org/sax/features/namespaces). */ | |
66 | private static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces"; | |
67 | ||
68 | /** Validation feature id (http://xml.org/sax/features/validation). */ | |
69 | private static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation"; | |
70 | ||
71 | /** SAX parser. */ | |
72 | private final XMLReader reader; | |
73 | ||
74 | /** Search for this simple XPath expression. */ | |
75 | private final SimpleXPath find; | |
76 | ||
77 | /** We are currently at this position. */ | |
78 | private SimpleXPath current; | |
79 | ||
80 | /** We are currently at this position if we count only occurrences and take every element. The | |
81 | * elements are all named "*". */ | |
82 | private SimpleXPath summary; | |
83 | ||
84 | /** This object is parsed. */ | |
85 | private File xmlFile; | |
86 | ||
87 | /** Element stack. */ | |
88 | private final List elements; | |
89 | ||
90 | /** Current stack level. */ | |
91 | private int level; | |
92 | ||
93 | /** Add this to found position. */ | |
94 | private SourcePosition startDelta; | |
95 | ||
96 | /** Add this to found position. */ | |
97 | private SourcePosition endDelta; | |
98 | ||
99 | /** Here the found element starts. */ | |
100 | private SourcePosition start; | |
101 | ||
102 | /** Here the found element ends. */ | |
103 | private SourcePosition end; | |
104 | ||
105 | /** | |
106 | * Search simple XPath within an XML file. | |
107 | * | |
108 | * @param xmlFile Search this file. | |
109 | * @param xpath Search for this simple XPath. | |
110 | * @return Source position information. | |
111 | * @throws ParserConfigurationException Parser configuration problem. | |
112 | * @throws SAXException XML problem. | |
113 | * @throws IOException IO problem. | |
114 | */ | |
115 | // public static final SimpleXPath getXPathLocation(final File xmlFile, final String xpath) | |
116 | // throws ParserConfigurationException, SAXException, IOException { | |
117 | // return getXPathLocation(xmlFile, new SimpleXPath(xpath)); | |
118 | // } | |
119 | ||
120 | /** | |
121 | * Search simple XPath within an XML file. | |
122 | * If the system property "qedeq.test.xmlLocationFailures" is set to "true" a runtime | |
123 | * exception is thrown if the path is not found. | |
124 | * | |
125 | * @param address Name description (for example URL) for this XML file. | |
126 | * @param xpath Search for this simple XPath. | |
127 | * @param startDelta Skip position (relative to location start). Could be | |
128 | * <code>null</code>. | |
129 | * @param endDelta Mark until this column (relative to location start). Could | |
130 | * be <code>null</code>. | |
131 | * @param file Search this file. | |
132 | * @return Source position information. | |
133 | */ | |
134 | 66766 | public static SourceArea findSourceArea(final String address, final SimpleXPath xpath, |
135 | final SourcePosition startDelta, final SourcePosition endDelta, final File file) { | |
136 | 66766 | final String method = "findSourceArea(String, SimpleXPath, SourcePosition, SourcePosition, File)"; |
137 | 66766 | final String message = "Could not find \"" + xpath + "\" within \"" + file + "\""; |
138 | 66766 | try { |
139 | 66766 | XPathLocationParser parser = new XPathLocationParser(xpath, startDelta, endDelta); |
140 | 66766 | parser.parse(file); |
141 | 66765 | if (parser.getStart() == null || parser.getEnd() == null) { |
142 | 1 | Trace.fatal(CLASS, method, message, null); |
143 | 1 | if (Boolean.TRUE.toString().equalsIgnoreCase( |
144 | System.getProperty("qedeq.test.xmlLocationFailures"))) { | |
145 | 0 | throw new RuntimeException(message); |
146 | } | |
147 | 1 | return new SourceArea(address); |
148 | } | |
149 | 66764 | return new SourceArea(address, parser.getStart(), parser.getEnd()); |
150 | } catch (ParserConfigurationException e) { | |
151 | 0 | Trace.fatal(CLASS, method, message, e); |
152 | } catch (SAXException e) { | |
153 | 0 | Trace.fatal(CLASS, method, message, e); |
154 | } catch (IOException e) { | |
155 | 1 | Trace.fatal(CLASS, method, message, e); |
156 | } catch (RuntimeException e) { | |
157 | 0 | Trace.fatal(CLASS, method, message, e); |
158 | } | |
159 | 1 | return null; |
160 | } | |
161 | ||
162 | /** | |
163 | * Search simple XPath within an XML file. | |
164 | * If the system property "qedeq.test.xmlLocationFailures" is set to "true" a runtime | |
165 | * exception is thrown if the path is not found. | |
166 | * | |
167 | * @param file Search this file. | |
168 | * @param xpath Search for this simple XPath. | |
169 | * @return Source position information. | |
170 | */ | |
171 | 66442 | public static SourceArea findSourceArea(final File file, final SimpleXPath xpath) { |
172 | 66442 | return findSourceArea(file.toString(), xpath, null, null, file); |
173 | } | |
174 | ||
175 | /** | |
176 | * Constructor. | |
177 | * | |
178 | * @param xpath XML file path. | |
179 | * @param startDelta Skip position (relative to location start). Could be | |
180 | * <code>null</code>. | |
181 | * @param endDelta Mark until this column (relative to location start). Could | |
182 | * be <code>null</code>. | |
183 | * @throws ParserConfigurationException Severe parser configuration problem. | |
184 | * @throws SAXException XML problem. | |
185 | */ | |
186 | 66766 | public XPathLocationParser(final SimpleXPath xpath, final SourcePosition startDelta, |
187 | final SourcePosition endDelta) throws ParserConfigurationException, | |
188 | SAXException { | |
189 | 66766 | super(); |
190 | ||
191 | 66766 | this.find = xpath; |
192 | 66766 | this.startDelta = startDelta; |
193 | 66766 | this.endDelta = endDelta; |
194 | 66766 | elements = new ArrayList(20); |
195 | 66766 | level = 0; |
196 | ||
197 | 66766 | final String factoryImpl = System.getProperty("javax.xml.parsers.SAXParserFactory"); |
198 | 66766 | if (factoryImpl == null) { |
199 | 2 | System.setProperty("javax.xml.parsers.SAXParserFactory", |
200 | "org.apache.xerces.jaxp.SAXParserFactoryImpl"); | |
201 | } | |
202 | 66766 | SAXParserFactory factory = SAXParserFactory.newInstance(); |
203 | 66766 | factory.setNamespaceAware(false); |
204 | 66766 | factory.setValidating(false); |
205 | ||
206 | 66766 | factory.setFeature(NAMESPACES_FEATURE_ID, false); |
207 | 66766 | factory.setFeature(VALIDATION_FEATURE_ID, false); |
208 | ||
209 | 66766 | final SAXParser parser = factory.newSAXParser(); |
210 | ||
211 | 66766 | reader = parser.getXMLReader(); |
212 | ||
213 | // set parser features | |
214 | 66766 | reader.setFeature(NAMESPACES_FEATURE_ID, false); |
215 | 66766 | reader.setFeature(VALIDATION_FEATURE_ID, false); |
216 | } | |
217 | ||
218 | /** | |
219 | * Parses XML file. | |
220 | * | |
221 | * @param file Parse this input. | |
222 | * @throws IOException Technical problem occurred. | |
223 | * @throws SAXException Parsing problem. | |
224 | */ | |
225 | 66766 | public final void parse(final File file) throws IOException, SAXException { |
226 | 66766 | xmlFile = file; |
227 | 66766 | elements.clear(); |
228 | 66766 | level = 0; |
229 | 66766 | InputStream stream = null; |
230 | 66766 | try { |
231 | 66766 | current = new SimpleXPath(); |
232 | 66766 | summary = new SimpleXPath(); |
233 | 66766 | reader.setContentHandler(this); |
234 | // LATER 20110316 m31: this seems to have no effect, the error handler don't get the Exceptions! Why? | |
235 | // reader.setErrorHandler(new ErrorHandler() { | |
236 | // | |
237 | // public void error(SAXParseException exception) throws SAXException { | |
238 | // exception.printStackTrace(System.out); | |
239 | //// throw exception; | |
240 | // } | |
241 | // | |
242 | // public void fatalError(SAXParseException exception) { | |
243 | // exception.printStackTrace(System.out); | |
244 | // } | |
245 | // | |
246 | // public void warning(SAXParseException exception) | |
247 | // throws SAXException { | |
248 | // exception.printStackTrace(System.out); | |
249 | // }}); | |
250 | 66766 | stream = new FileInputStream(file); |
251 | 66765 | reader.parse(new InputSource(stream)); |
252 | } catch (XPathLocationFoundException e) { | |
253 | // this is what we want!!! | |
254 | } catch (SAXException e) { | |
255 | 0 | Trace.trace(CLASS, this, "parse", e); |
256 | 0 | throw e; |
257 | } finally { | |
258 | 66766 | IoUtility.close(stream); |
259 | } | |
260 | } | |
261 | ||
262 | /* | |
263 | * (non-Javadoc) | |
264 | * | |
265 | * @see org.xml.sax.ContentHandler#endDocument() | |
266 | */ | |
267 | 35 | public void endDocument() throws SAXException { |
268 | 35 | elements.clear(); |
269 | 35 | level = 0; |
270 | } | |
271 | ||
272 | /* | |
273 | * (non-Javadoc) | |
274 | * | |
275 | * @see org.xml.sax.ContentHandler#startDocument() | |
276 | */ | |
277 | 66765 | public void startDocument() throws SAXException { |
278 | 66765 | elements.clear(); |
279 | 66765 | level = 0; |
280 | } | |
281 | ||
282 | /* | |
283 | * (non-Javadoc) | |
284 | * | |
285 | * @see org.xml.sax.ContentHandler#characters(char[], int, int) | |
286 | */ | |
287 | 229613973 | public void characters(final char[] ch, final int start, final int length) throws SAXException { |
288 | // nothing to do | |
289 | } | |
290 | ||
291 | /* | |
292 | * (non-Javadoc) | |
293 | * | |
294 | * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) | |
295 | */ | |
296 | 0 | public void ignorableWhitespace(final char[] ch, final int start, final int length) |
297 | throws SAXException { | |
298 | // nothing to do | |
299 | } | |
300 | ||
301 | /* | |
302 | * (non-Javadoc) | |
303 | * | |
304 | * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) | |
305 | */ | |
306 | 0 | public void endPrefixMapping(final String prefix) throws SAXException { |
307 | // nothing to do | |
308 | } | |
309 | ||
310 | /* | |
311 | * (non-Javadoc) | |
312 | * | |
313 | * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) | |
314 | */ | |
315 | 0 | public void skippedEntity(final String name) throws SAXException { |
316 | // nothing to do | |
317 | } | |
318 | ||
319 | /* | |
320 | * (non-Javadoc) | |
321 | * | |
322 | * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) | |
323 | */ | |
324 | 0 | public void processingInstruction(final String target, final String data) throws SAXException { |
325 | // nothing to do | |
326 | } | |
327 | ||
328 | /* | |
329 | * (non-Javadoc) | |
330 | * | |
331 | * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) | |
332 | */ | |
333 | 0 | public void startPrefixMapping(final String prefix, final String uri) throws SAXException { |
334 | // nothing to do | |
335 | } | |
336 | ||
337 | /* | |
338 | * (non-Javadoc) | |
339 | * | |
340 | * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, | |
341 | * java.lang.String, org.xml.sax.Attributes) | |
342 | */ | |
343 | 106586873 | public void startElement(final String namespaceURI, final String localName, final String qName, |
344 | final Attributes atts) throws SAXException { | |
345 | 106586873 | final String method = "startElement(String, String, Attributes)"; |
346 | 106586873 | level++; |
347 | 106586873 | summary.addElement("*", addOccurence("*")); |
348 | 106586873 | current.addElement(qName, addOccurence(qName)); |
349 | ||
350 | // LATER mime 20070109: just for testing is the next if | |
351 | /* | |
352 | if (find.matchesElementsBegining(current, summary)) { | |
353 | System.out.println("part match " + qName); | |
354 | xml.setRow(locator.getLineNumber()); | |
355 | xml.setColumn(locator.getColumnNumber()); | |
356 | try { | |
357 | xml.skipBackToBeginOfXmlTag(); | |
358 | } catch (RuntimeException e) { | |
359 | Trace.trace(this, method, e); | |
360 | } | |
361 | find.setStartLocation(new SourcePosition(xml.getLocalAddress(), xml.getRow(), xml | |
362 | .getColumn())); | |
363 | } | |
364 | */ | |
365 | 106586873 | if (getLocator() == null) { |
366 | 0 | throw new SAXException("Locator unexpectedly null"); |
367 | } | |
368 | 106586873 | if (find.matchesElements(current, summary)) { |
369 | 66764 | Trace.trace(CLASS, this, method, "matching elements"); |
370 | 66764 | Trace.param(CLASS, this, method, qName, current); |
371 | 66764 | TextInput xml = null; |
372 | 66764 | Reader xmlReader = null; |
373 | 66764 | try { |
374 | 66764 | xmlReader = new XmlReader(xmlFile); |
375 | 66764 | xml = new TextInput(xmlReader); |
376 | // LATER mime 20080608: old code | |
377 | // xml = new TextInput(xmlFile, IoUtility.getWorkingEncoding(getEncoding())); | |
378 | } catch (IOException io) { | |
379 | 0 | Trace.fatal(CLASS, this, method, "File \"" + xmlFile + "\" should be readable", io); |
380 | 0 | if (getLocator() == null) { |
381 | 0 | throw new SAXException("Locator unexpectedly null"); |
382 | } | |
383 | // at least we can set the current location as find location | |
384 | 0 | start = new SourcePosition( |
385 | getLocator().getLineNumber(), getLocator().getColumnNumber()); | |
386 | 0 | return; |
387 | } | |
388 | 66764 | try { |
389 | 66764 | xml.setRow(getLocator().getLineNumber()); |
390 | 66764 | xml.setColumn(getLocator().getColumnNumber()); |
391 | 66764 | if (startDelta != null) { |
392 | 34 | xml.skipWhiteSpace(); |
393 | 34 | final String cdata = "<![CDATA["; |
394 | 34 | final String read = xml.readString(cdata.length()); |
395 | 34 | final int cdataLength = (cdata.equals(read) ? cdata.length() : 0); |
396 | 34 | start = addDelta(xml, cdataLength, startDelta); |
397 | 34 | end = addDelta(xml, cdataLength, endDelta); |
398 | 34 | return; |
399 | } | |
400 | 66730 | try { |
401 | 66730 | xml.skipBackToBeginOfXmlTag(); |
402 | } catch (RuntimeException e) { | |
403 | 0 | Trace.trace(CLASS, this, method, e); |
404 | } | |
405 | 66730 | start = new SourcePosition(xml.getRow(), xml.getColumn()); |
406 | 66730 | if (find.getAttribute() != null) { |
407 | 4557 | xml.read(); // skip < |
408 | 4557 | xml.readNextXmlName(); // must be element name |
409 | 4557 | String tag; |
410 | 4557 | do { |
411 | 5096 | xml.skipWhiteSpace(); |
412 | 5096 | int row = xml.getRow(); |
413 | 5096 | int col = xml.getColumn(); |
414 | 5096 | try { |
415 | 5096 | tag = xml.readNextXmlName(); |
416 | } catch (IllegalArgumentException e) { | |
417 | 10 | break; |
418 | } | |
419 | 5086 | if (tag.equals(find.getAttribute())) { |
420 | 4535 | start = new SourcePosition(row, col); |
421 | 4535 | xml.readNextAttributeValue(); |
422 | 4535 | end = new SourcePosition(xml.getRow(), xml.getColumn()); |
423 | 4535 | throw new XPathLocationFoundException(); |
424 | } | |
425 | 551 | try { |
426 | 551 | xml.readNextAttributeValue(); |
427 | } catch (IllegalArgumentException e) { | |
428 | 12 | break; |
429 | } | |
430 | } while (true); | |
431 | // did we found the attribute? if not we point to the complete xml tag | |
432 | 22 | if (end == null) { |
433 | 22 | end = new SourcePosition(xml.getRow(), xml.getColumn()); |
434 | 22 | throw new XPathLocationFoundException(); |
435 | } | |
436 | } | |
437 | } finally { | |
438 | 66764 | IoUtility.close(xml); // findbugs |
439 | } | |
440 | } | |
441 | } | |
442 | ||
443 | /** | |
444 | * Set text input position according to locator and add delta plus tag length. | |
445 | * | |
446 | * @param xml This is the stream we work on. | |
447 | * @param cdataLength Length of extra skip data. | |
448 | * @param delta Add this delta | |
449 | * @return Resulting source position. | |
450 | */ | |
451 | 68 | private SourcePosition addDelta(final TextInput xml, final int cdataLength, |
452 | final SourcePosition delta) { | |
453 | 68 | xml.setRow(getLocator().getLineNumber()); |
454 | 68 | xml.setColumn(getLocator().getColumnNumber()); |
455 | 68 | if (delta.getRow() == 1 && cdataLength > 0) { |
456 | 0 | xml.addColumn(cdataLength + delta.getColumn() - 1); |
457 | } else { | |
458 | 68 | xml.addPosition(delta); |
459 | } | |
460 | 68 | return new SourcePosition(xml.getRow(), xml.getColumn()); |
461 | } | |
462 | ||
463 | /** | |
464 | * Add element occurrence. | |
465 | * | |
466 | * @param name Element that occurred. | |
467 | * @return Number of occurrences including this one. | |
468 | */ | |
469 | 213173746 | private int addOccurence(final String name) { |
470 | 269625761 | while (level < elements.size()) { |
471 | 56452015 | elements.remove(elements.size() - 1); |
472 | } | |
473 | 270402640 | while (level > elements.size()) { |
474 | 57228894 | elements.add(new HashMap()); |
475 | } | |
476 | 213173746 | final Map levelMap = (Map) elements.get(level - 1); |
477 | 213173746 | final Enumerator counter; |
478 | 213173746 | if (levelMap.containsKey(name)) { |
479 | 76071240 | counter = (Enumerator) levelMap.get(name); |
480 | 76071240 | counter.increaseNumber(); |
481 | } else { | |
482 | 137102506 | counter = new Enumerator(1); |
483 | 137102506 | levelMap.put(name, counter); |
484 | } | |
485 | 213173746 | return counter.getNumber(); |
486 | } | |
487 | ||
488 | /* | |
489 | * (non-Javadoc) | |
490 | * | |
491 | * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, | |
492 | * java.lang.String) | |
493 | */ | |
494 | 105947374 | public void endElement(final String namespaceURI, final String localName, final String qName) |
495 | throws SAXException { | |
496 | 105947374 | final String method = "endElement(String, String, Attributes)"; |
497 | 105947374 | level--; |
498 | 105947374 | if (getLocator() == null) { |
499 | 0 | current.deleteLastElement(); |
500 | 0 | summary.deleteLastElement(); |
501 | 0 | throw new SAXException("Locator unexpectly null"); |
502 | } | |
503 | 105947374 | if (find.matchesElements(current, summary) && find.getAttribute() == null |
504 | && startDelta == null) { | |
505 | 62173 | TextInput xml = null; |
506 | 62173 | Reader xmlReader = null; |
507 | 62173 | try { |
508 | 62173 | xmlReader = new XmlReader(xmlFile); |
509 | 62173 | xml = new TextInput(xmlReader); |
510 | // LATER mime 20080608: old code | |
511 | // xml = new TextInput(xmlFile, IoUtility.getWorkingEncoding(getEncoding())); | |
512 | } catch (IOException io) { | |
513 | 0 | Trace.fatal(CLASS, this, method, "File \"" + xmlFile + "\" should be readable", io); |
514 | 0 | if (getLocator() == null) { |
515 | 0 | throw new SAXException("Locator unexpectedly null"); |
516 | } | |
517 | // at least we can set the current location as find location | |
518 | 0 | start = new SourcePosition(getLocator().getLineNumber(), |
519 | getLocator().getColumnNumber()); | |
520 | 0 | return; |
521 | } finally { | |
522 | 62173 | IoUtility.close(xmlReader); |
523 | } | |
524 | 62173 | try { |
525 | 62173 | xml.setRow(getLocator().getLineNumber()); |
526 | 62173 | xml.setColumn(getLocator().getColumnNumber()); |
527 | // xml.skipForwardToEndOfXmlTag(); // LATER mime 20050810: remove? comment in? | |
528 | 62173 | end = new SourcePosition(xml.getRow(), xml.getColumn()); |
529 | 62173 | throw new XPathLocationFoundException(); |
530 | } finally { | |
531 | 62173 | IoUtility.close(xml); // findbugs |
532 | } | |
533 | } | |
534 | 105885201 | current.deleteLastElement(); |
535 | 105885201 | summary.deleteLastElement(); |
536 | } | |
537 | ||
538 | /** | |
539 | * Get starting source position of found element. Could be <code>null</code>. | |
540 | * | |
541 | * @return Start position. | |
542 | */ | |
543 | 133529 | private SourcePosition getStart() { |
544 | 133529 | return start; |
545 | } | |
546 | ||
547 | /** | |
548 | * Get ending source position of found element. Could be <code>null</code>. | |
549 | * | |
550 | * @return End position. | |
551 | */ | |
552 | 133528 | private SourcePosition getEnd() { |
553 | 133528 | return end; |
554 | } | |
555 | ||
556 | } |
|