Skip to content

Commit 4480258

Browse files
ivandalboscopynicolas
authored andcommitted
SONARPY-174 Stop using StaxParser of sonar-api (SonarSource#69)
* SONARPY-174 Stop using StaxParser of sonar-api * Add dependency to woodstox-core-lgpl in order to allow SonarLint to avoid providing class WstxEOFException * SONARPY-174 Post-rewiew fix: apply change to PythonXUnitSensor * SONARPY-174 Post-rewiew fix: remove useless code in StaxParser * SONARPY-174 Post-review fixes
1 parent cda6365 commit 4480258

13 files changed

Lines changed: 224 additions & 8 deletions

File tree

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<sonarlint-core.version>2.4.1</sonarlint-core.version>
9090
<sslr.version>1.21</sslr.version>
9191
<sslr.squid.bridge.version>2.6.1</sslr.squid.bridge.version>
92+
<woodstox.version>4.4.1</woodstox.version>
9293
</properties>
9394

9495
<dependencyManagement>
@@ -149,6 +150,11 @@
149150
<artifactId>slf4j-api</artifactId>
150151
<version>${slf4j.version}</version>
151152
</dependency>
153+
<dependency>
154+
<groupId>org.codehaus.woodstox</groupId>
155+
<artifactId>woodstox-core-lgpl</artifactId>
156+
<version>${woodstox.version}</version>
157+
</dependency>
152158
<dependency>
153159
<groupId>ch.qos.logback</groupId>
154160
<artifactId>logback-classic</artifactId>

sonar-python-plugin/pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
<groupId>commons-lang</groupId>
5252
<artifactId>commons-lang</artifactId>
5353
</dependency>
54+
<dependency>
55+
<groupId>org.codehaus.woodstox</groupId>
56+
<artifactId>woodstox-core-lgpl</artifactId>
57+
</dependency>
5458
<dependency>
5559
<groupId>org.apache.maven</groupId>
5660
<artifactId>maven-project</artifactId>
@@ -97,8 +101,8 @@
97101
<configuration>
98102
<rules>
99103
<requireFilesSize>
100-
<minsize>2900000</minsize>
101-
<maxsize>3100000</maxsize>
104+
<minsize>3600000</minsize>
105+
<maxsize>3800000</maxsize>
102106
<files>
103107
<file>${project.build.directory}/${project.build.finalName}.jar</file>
104108
</files>

sonar-python-plugin/src/main/java/org/sonar/plugins/python/coverage/CoberturaParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
import org.sonar.api.batch.fs.InputFile;
3030
import org.sonar.api.batch.sensor.SensorContext;
3131
import org.sonar.api.batch.sensor.coverage.NewCoverage;
32-
import org.sonar.api.utils.StaxParser;
3332
import org.sonar.plugins.python.EmptyReportException;
33+
import org.sonar.plugins.python.parser.StaxParser;
3434

3535
public class CoberturaParser {
3636

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2016 SonarSource SA
4+
* mailto:contact AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.plugins.python.parser;
21+
22+
import com.ctc.wstx.stax.WstxInputFactory;
23+
import java.io.File;
24+
import java.io.FileInputStream;
25+
import java.io.IOException;
26+
import java.io.InputStream;
27+
import javax.xml.stream.XMLInputFactory;
28+
import javax.xml.stream.XMLResolver;
29+
import javax.xml.stream.XMLStreamException;
30+
import org.apache.commons.lang.StringUtils;
31+
import org.codehaus.staxmate.SMInputFactory;
32+
import org.codehaus.staxmate.in.SMHierarchicCursor;
33+
34+
/**
35+
* Class copied from deprecated class StaxParser of sonar-plugin-api.
36+
*/
37+
public class StaxParser {
38+
39+
private SMInputFactory inf;
40+
41+
private XmlStreamHandler streamHandler;
42+
43+
public StaxParser(XmlStreamHandler streamHandler) {
44+
this.streamHandler = streamHandler;
45+
WstxInputFactory xmlFactory = (WstxInputFactory) XMLInputFactory.newInstance();
46+
xmlFactory.configureForLowMemUsage();
47+
xmlFactory.getConfig().setUndeclaredEntityResolver(new UndeclaredEntitiesXMLResolver());
48+
xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
49+
xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
50+
xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
51+
inf = new SMInputFactory(xmlFactory);
52+
}
53+
54+
public void parse(File xmlFile) throws XMLStreamException {
55+
try (FileInputStream input = new FileInputStream(xmlFile)) {
56+
parse(input);
57+
} catch (IOException e) {
58+
throw new XMLStreamException(e);
59+
}
60+
}
61+
62+
public void parse(InputStream xmlInput) throws XMLStreamException {
63+
SMHierarchicCursor rootCursor = inf.rootElementCursor(xmlInput);
64+
try {
65+
streamHandler.stream(rootCursor);
66+
} finally {
67+
rootCursor.getStreamReader().closeCompletely();
68+
}
69+
}
70+
71+
private static class UndeclaredEntitiesXMLResolver implements XMLResolver {
72+
73+
@Override
74+
public Object resolveEntity(String arg0, String arg1, String fileName, String undeclaredEntity) throws XMLStreamException {
75+
String undeclared = undeclaredEntity;
76+
// avoid problems with XML docs containing undeclared entities.. return the entity under its raw form if not a Unicode expression
77+
if (StringUtils.startsWithIgnoreCase(undeclaredEntity, "u") && undeclaredEntity.length() == 5) {
78+
int unicodeCharHexValue = Integer.parseInt(undeclaredEntity.substring(1), 16);
79+
if (Character.isDefined(unicodeCharHexValue)) {
80+
undeclared = new String(new char[] {(char) unicodeCharHexValue});
81+
}
82+
}
83+
return undeclared;
84+
}
85+
}
86+
87+
/**
88+
* Simple interface for handling XML stream to parse.
89+
*/
90+
@FunctionalInterface
91+
public interface XmlStreamHandler {
92+
void stream(SMHierarchicCursor rootCursor) throws XMLStreamException;
93+
}
94+
95+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2016 SonarSource SA
4+
* mailto:contact AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
@ParametersAreNonnullByDefault
21+
package org.sonar.plugins.python.parser;
22+
23+
import javax.annotation.ParametersAreNonnullByDefault;

sonar-python-plugin/src/main/java/org/sonar/plugins/python/xunit/PythonXUnitSensor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
import org.sonar.api.batch.fs.InputFile;
3434
import org.sonar.api.config.Settings;
3535
import org.sonar.api.measures.CoreMetrics;
36-
import org.sonar.api.utils.StaxParser;
3736
import org.sonar.plugins.python.PythonReportSensor;
37+
import org.sonar.plugins.python.parser.StaxParser;
3838

3939
public class PythonXUnitSensor extends PythonReportSensor {
4040
private static final Logger LOG = LoggerFactory.getLogger(PythonXUnitSensor.class);
@@ -68,7 +68,7 @@ protected void processReports(final SensorContext context, List<File> reports) t
6868

6969
private static void simpleMode(final SensorContext context, List<File> reports) throws XMLStreamException {
7070
TestSuiteParser parserHandler = new TestSuiteParser();
71-
StaxParser parser = new StaxParser(parserHandler, false);
71+
StaxParser parser = new StaxParser(parserHandler);
7272
for (File report : reports) {
7373
parser.parse(report);
7474
}
@@ -98,7 +98,7 @@ private static void simpleMode(final SensorContext context, List<File> reports)
9898
private void detailedMode(final SensorContext context, List<File> reports) throws XMLStreamException {
9999
for (File report : reports) {
100100
TestSuiteParser parserHandler = new TestSuiteParser();
101-
StaxParser parser = new StaxParser(parserHandler, false);
101+
StaxParser parser = new StaxParser(parserHandler);
102102
parser.parse(report);
103103

104104
LOG.info("Processing report '{}'", report);

sonar-python-plugin/src/main/java/org/sonar/plugins/python/xunit/TestSuiteParser.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
import org.codehaus.staxmate.in.SMHierarchicCursor;
2424
import org.codehaus.staxmate.in.SMInputCursor;
2525
import org.sonar.api.utils.ParsingUtils;
26-
import org.sonar.api.utils.StaxParser.XmlStreamHandler;
27-
26+
import org.sonar.plugins.python.parser.StaxParser.XmlStreamHandler;
2827
import javax.xml.stream.XMLStreamException;
2928
import java.text.ParseException;
3029
import java.util.Collection;

sonar-python-plugin/src/test/java/org/sonar/plugins/python/coverage/PythonCoverageSensorTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public void test_coverage() {
124124
assertThat(context.conditions(FILE2_KEY, CoverageType.UNIT, 3)).isEqualTo(2);
125125
assertThat(context.coveredConditions(FILE2_KEY, CoverageType.UNIT, 3)).isEqualTo(1);
126126
}
127+
127128
@Test
128129
public void test_unresolved_path() {
129130
settings.setProperty(PythonCoverageSensor.REPORT_PATH_KEY, "coverage_with_unresolved_path.xml");
@@ -160,6 +161,12 @@ public void should_fail_on_invalid_report() {
160161
coverageSensor.execute(context, linesOfCode);
161162
}
162163

164+
@Test(expected = IllegalStateException.class)
165+
public void should_fail_on_unexpected_eof() {
166+
settings.setProperty(PythonCoverageSensor.REPORT_PATH_KEY, "coverage_with_eof_error.xml");
167+
coverageSensor.execute(context, linesOfCode);
168+
}
169+
163170
@Test
164171
public void should_do_nothing_on_empty_report() {
165172
settings.setProperty(PythonCoverageSensor.REPORT_PATH_KEY, "empty-coverage-result.xml");
@@ -168,4 +175,5 @@ public void should_do_nothing_on_empty_report() {
168175

169176
assertThat(context.lineHits(FILE1_KEY, CoverageType.UNIT, 1)).isNull();
170177
}
178+
171179
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2016 SonarSource SA
4+
* mailto:contact AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.plugins.python.parser;
21+
22+
import javax.xml.stream.XMLStreamException;
23+
import org.codehaus.staxmate.in.SMHierarchicCursor;
24+
import org.junit.Test;
25+
import org.sonar.plugins.python.parser.StaxParser.XmlStreamHandler;
26+
27+
public class StaxParserTest {
28+
29+
@Test
30+
public void test_XML_with_DTD() throws XMLStreamException {
31+
StaxParser parser = new StaxParser(getTestHandler());
32+
parser.parse(getClass().getClassLoader().getResourceAsStream("org/sonar/plugins/python/parser/dtd-test.xml"));
33+
}
34+
35+
@Test
36+
public void test_XML_with_XSD() throws XMLStreamException {
37+
StaxParser parser = new StaxParser(getTestHandler());
38+
parser.parse(getClass().getClassLoader().getResourceAsStream("org/sonar/plugins/python/parser/xsd-test.xml"));
39+
}
40+
41+
@Test
42+
public void test_XML_with_XSD_and_ampersand() throws XMLStreamException {
43+
StaxParser parser = new StaxParser(getTestHandler());
44+
parser.parse(getClass().getClassLoader().getResourceAsStream("org/sonar/plugins/python/parser/xsd-test-with-entity.xml"));
45+
}
46+
47+
private XmlStreamHandler getTestHandler() {
48+
return new XmlStreamHandler() {
49+
public void stream(SMHierarchicCursor rootCursor) throws XMLStreamException {
50+
rootCursor.advance();
51+
while (rootCursor.getNext() != null) {
52+
}
53+
}
54+
};
55+
}
56+
57+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" ?>
2+
<coverage>
3+
<packages>
4+
<package>
5+
<classes>

0 commit comments

Comments
 (0)