[core] Fix java7 compatibility

* Scala also requires java8 and it failed indirectly via a
  ServiceConfigurationError while discovering the language.
  Scala's dependencies require java8.
* Downgrade JCommander for java7 compatibility
* Downgrade commons-text for java7 compatibility
* Add integration test
This commit is contained in:
Andreas Dangel
2020-08-01 17:53:45 +02:00
parent fc99e92a7e
commit 4cf9f5904a
11 changed files with 136 additions and 26 deletions

View File

@ -18,6 +18,24 @@ if travis_isLinux; then
bundle config set --local path vendor/bundle bundle config set --local path vendor/bundle
bundle config set --local with release_notes_preprocessing bundle config set --local with release_notes_preprocessing
bundle install bundle install
# install jdk7 for integration test
LOCAL_DIR=${HOME}/.cache/jdk7
TARGET_DIR=${HOME}/oraclejdk7
JDK7_ARCHIVE=jdk-7u80-linux-x64.tar.gz
DOWNLOAD_URL=https://pmd-code.org/oraclejdk/${JDK7_ARCHIVE}
mkdir -p ${LOCAL_DIR}
mkdir -p ${TARGET_DIR}
if [ ! -e ${LOCAL_DIR}/${JDK7_ARCHIVE} ]; then
log_info "Downloading from ${DOWNLOAD_URL} to ${LOCAL_DIR}"
wget --directory-prefix ${LOCAL_DIR} --timestamping --continue ${DOWNLOAD_URL}
else
log_info "Skipped download, file ${LOCAL_DIR}/${JDK7_ARCHIVE} already exists"
fi
log_info "Extracting to ${TARGET_DIR}"
tar --extract --file ${LOCAL_DIR}/${JDK7_ARCHIVE} -C ${TARGET_DIR} --strip-components=1
log_info "OracleJDK7 can be used via -Djava7.home=${TARGET_DIR}"
else else
log_info "Not setting up ruby for ${TRAVIS_OS_NAME}." log_info "Not setting up ruby for ${TRAVIS_OS_NAME}."
exit 0 exit 0

View File

@ -10,7 +10,11 @@ source .travis/regression-tester.sh
VERSION=$(get_pom_version) VERSION=$(get_pom_version)
log_info "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}" log_info "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}"
MVN_BUILD_FLAGS="-B -V" if travis_isLinux; then
MVN_BUILD_FLAGS="-B -V -Djava7.home=${HOME}/oraclejdk7"
else
MVN_BUILD_FLAGS="-B -V"
fi
if travis_isOSX; then if travis_isOSX; then

View File

@ -14,6 +14,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader; import java.util.ServiceLoader;
public final class LanguageFactory { public final class LanguageFactory {
@ -40,7 +41,7 @@ public final class LanguageFactory {
try { try {
Language language = iterator.next(); Language language = iterator.next();
languagesList.add(language); languagesList.add(language);
} catch (UnsupportedClassVersionError e) { } catch (ServiceConfigurationError | UnsupportedClassVersionError e) {
// Some languages require java8 and are therefore only available // Some languages require java8 and are therefore only available
// if java8 or later is used as runtime. // if java8 or later is used as runtime.
System.err.println("Ignoring language for CPD: " + e.toString()); System.err.println("Ignoring language for CPD: " + e.toString());

View File

@ -12,6 +12,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -34,7 +35,7 @@ public final class LanguageRegistry {
try { try {
Language language = iterator.next(); Language language = iterator.next();
languagesList.add(language); languagesList.add(language);
} catch (UnsupportedClassVersionError e) { } catch (ServiceConfigurationError | UnsupportedClassVersionError e) {
// Some languages require java8 and are therefore only available // Some languages require java8 and are therefore only available
// if java8 or later is used as runtime. // if java8 or later is used as runtime.
System.err.println("Ignoring language for PMD: " + e.toString()); System.err.println("Ignoring language for PMD: " + e.toString());

View File

@ -59,9 +59,8 @@ public class TreeExportCli {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
TreeExportCli cli = new TreeExportCli(); TreeExportCli cli = new TreeExportCli();
JCommander jcommander = JCommander.newBuilder() JCommander jcommander = new JCommander(cli);
.addObject(cli)
.build();
try { try {
jcommander.parse(args); jcommander.parse(args);
} catch (ParameterException e) { } catch (ParameterException e) {

View File

@ -80,9 +80,9 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId> <artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<executions> <executions>
<execution> <execution>
<id>failsafe-default</id>
<goals> <goals>
<goal>integration-test</goal> <goal>integration-test</goal>
<goal>verify</goal> <goal>verify</goal>
@ -198,11 +198,6 @@
<artifactId>pmd-ruby</artifactId> <artifactId>pmd-ruby</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-scala_2.13</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>net.sourceforge.pmd</groupId> <groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-swift</artifactId> <artifactId>pmd-swift</artifactId>
@ -259,6 +254,11 @@
<artifactId>pmd-apex</artifactId> <artifactId>pmd-apex</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-scala_2.13</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>net.sourceforge.pmd</groupId> <groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-ui</artifactId> <artifactId>pmd-ui</artifactId>
@ -266,5 +266,36 @@
</dependency> </dependency>
</dependencies> </dependencies>
</profile> </profile>
<profile>
<id>jdk7-compat-it</id>
<activation>
<property>
<name>java7.home</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>jdk7-compat-it</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<environmentVariables>
<JAVA_HOME>${java7.home}</JAVA_HOME>
<PATH>${java7.home}/bin:${env.PATH}</PATH>
</environmentVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles> </profiles>
</project> </project>

View File

@ -21,6 +21,11 @@ public class AllRulesIT extends AbstractBinaryDistributionTest {
@Parameters @Parameters
public static Iterable<String> languagesToTest() { public static Iterable<String> languagesToTest() {
if (PMDExecutor.isJava7Test()) {
// note: apex and scala require java8
return Arrays.asList("java", "javascript", "jsp", "modelica",
"plsql", "pom", "visualforce", "velocitytemplate", "xml", "xsl");
}
// note: scala and wsdl have no rules // note: scala and wsdl have no rules
return Arrays.asList("java", "apex", "javascript", "jsp", "modelica", return Arrays.asList("java", "apex", "javascript", "jsp", "modelica",
"plsql", "pom", "visualforce", "velocitytemplate", "xml", "xsl"); "plsql", "pom", "visualforce", "velocitytemplate", "xml", "xsl");

View File

@ -1,4 +1,4 @@
/** /*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/ */
@ -21,7 +21,19 @@ import net.sourceforge.pmd.PMDVersion;
public class BinaryDistributionIT extends AbstractBinaryDistributionTest { public class BinaryDistributionIT extends AbstractBinaryDistributionTest {
private static final String SUPPORTED_LANGUAGES = "Supported languages: [apex, cpp, cs, dart, ecmascript, fortran, go, groovy, java, jsp, kotlin, lua, matlab, modelica, objectivec, perl, php, plsql, python, ruby, scala, swift, vf, xml]"; private static final String SUPPORTED_LANGUAGES_CPD;
private static final String SUPPORTED_LANGUAGES_PMD;
static {
// note: apex and scala require java8
if (PMDExecutor.isJava7Test()) {
SUPPORTED_LANGUAGES_CPD = "Supported languages: [cpp, cs, dart, ecmascript, fortran, go, groovy, java, jsp, kotlin, lua, matlab, modelica, objectivec, perl, php, plsql, python, ruby, swift, vf, xml]";
SUPPORTED_LANGUAGES_PMD = "ecmascript, java, jsp, modelica, plsql, pom, vf, vm, wsdl, xml, xsl";
} else {
SUPPORTED_LANGUAGES_CPD = "Supported languages: [apex, cpp, cs, dart, ecmascript, fortran, go, groovy, java, jsp, kotlin, lua, matlab, modelica, objectivec, perl, php, plsql, python, ruby, scala, swift, vf, xml]";
SUPPORTED_LANGUAGES_PMD = "apex, ecmascript, java, jsp, modelica, plsql, pom, scala, vf, vm, wsdl, xml, xsl";
}
}
@Test @Test
public void testFileExistence() { public void testFileExistence() {
@ -66,12 +78,20 @@ public class BinaryDistributionIT extends AbstractBinaryDistributionTest {
ExecutionResult result; ExecutionResult result;
result = PMDExecutor.runPMD(tempDir); // without any argument, display usage help and error
result.assertExecutionResult(1, SUPPORTED_LANGUAGES_PMD);
result = PMDExecutor.runPMD(tempDir, "-h"); result = PMDExecutor.runPMD(tempDir, "-h");
result.assertExecutionResult(0, "apex, ecmascript, java, jsp, modelica, plsql, pom, scala, vf, vm, wsdl, xml, xsl"); result.assertExecutionResult(0, SUPPORTED_LANGUAGES_PMD);
result = PMDExecutor.runPMDRules(tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml"); result = PMDExecutor.runPMDRules(tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml");
result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:"); result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:");
// also test XML format
result = PMDExecutor.runPMDRules(tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml", "xml");
result.assertExecutionResult(4, "", "JumbledIncrementer.java\">");
result.assertExecutionResult(4, "", "<violation beginline=\"8\" endline=\"10\" begincolumn=\"13\" endcolumn=\"13\" rule=\"JumbledIncrementer\"");
result = PMDExecutor.runPMDRules(tempDir, srcDir, "rulesets/java/quickstart.xml"); result = PMDExecutor.runPMDRules(tempDir, srcDir, "rulesets/java/quickstart.xml");
result.assertExecutionResult(4, ""); result.assertExecutionResult(4, "");
} }
@ -82,15 +102,23 @@ public class BinaryDistributionIT extends AbstractBinaryDistributionTest {
ExecutionResult result; ExecutionResult result;
result = CpdExecutor.runCpd(tempDir); // without any argument, display usage help and error
result.assertExecutionResult(1, SUPPORTED_LANGUAGES_CPD);
result = CpdExecutor.runCpd(tempDir, "-h"); result = CpdExecutor.runCpd(tempDir, "-h");
result.assertExecutionResult(0, SUPPORTED_LANGUAGES); result.assertExecutionResult(0, SUPPORTED_LANGUAGES_CPD);
result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "10", "--format", "text", "--files", srcDir); result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "10", "--format", "text", "--files", srcDir);
result.assertExecutionResult(4, "Found a 10 line (55 tokens) duplication in the following files:"); result.assertExecutionResult(4, "Found a 10 line (55 tokens) duplication in the following files:");
result.assertExecutionResult(4, "Class1.java"); result.assertExecutionResult(4, "Class1.java");
result.assertExecutionResult(4, "Class2.java"); result.assertExecutionResult(4, "Class2.java");
result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "10", "--format", "xml", "--files", srcDir);
result.assertExecutionResult(4, "<duplication lines=\"10\" tokens=\"55\">");
result.assertExecutionResult(4, "Class1.java\"/>");
result.assertExecutionResult(4, "Class2.java\"/>");
result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "1000", "--format", "text", "--files", srcDir); result = CpdExecutor.runCpd(tempDir, "--minimum-tokens", "1000", "--format", "text", "--files", srcDir);
result.assertExecutionResult(0, ""); result.assertExecutionResult(0);
} }
} }

View File

@ -42,6 +42,15 @@ public class ExecutionResult {
return sb.toString(); return sb.toString();
} }
/**
* Asserts that the command exited with the expected exit code. Any output is ignored.
*
* @param expectedExitCode the exit code, e.g. 0 if no rule violations are expected, or 4 if violations are found
*/
public void assertExecutionResult(int expectedExitCode) {
assertExecutionResult(expectedExitCode, null);
}
/** /**
* Asserts that the command exited with the expected exit code and that the given expected * Asserts that the command exited with the expected exit code and that the given expected
* output is contained in the actual command output. * output is contained in the actual command output.
@ -69,7 +78,7 @@ public class ExecutionResult {
if (!output.contains(expectedOutput)) { if (!output.contains(expectedOutput)) {
fail("Expected output '" + expectedOutput + "' not present.\nComplete result:\n\n" + this); fail("Expected output '" + expectedOutput + "' not present.\nComplete result:\n\n" + this);
} }
} else { } else if (expectedOutput != null && expectedOutput.isEmpty()) {
assertTrue("The output should have been empty.\nComplete result:\n\n" + this, output.isEmpty()); assertTrue("The output should have been empty.\nComplete result:\n\n" + this, output.isEmpty());
} }
if (expectedReport != null && !expectedReport.isEmpty()) { if (expectedReport != null && !expectedReport.isEmpty()) {

View File

@ -14,6 +14,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.PMDVersion;
@ -103,15 +104,19 @@ public class PMDExecutor {
* @throws Exception if the execution fails for any reason (executable not found, ...) * @throws Exception if the execution fails for any reason (executable not found, ...)
*/ */
public static ExecutionResult runPMDRules(Path tempDir, String sourceDirectory, String ruleset) throws Exception { public static ExecutionResult runPMDRules(Path tempDir, String sourceDirectory, String ruleset) throws Exception {
return runPMDRules(tempDir, sourceDirectory, ruleset, FORMATTER);
}
public static ExecutionResult runPMDRules(Path tempDir, String sourceDirectory, String ruleset, String formatter) throws Exception {
Path reportFile = Files.createTempFile("pmd-it-report", "txt"); Path reportFile = Files.createTempFile("pmd-it-report", "txt");
reportFile.toFile().deleteOnExit(); reportFile.toFile().deleteOnExit();
if (SystemUtils.IS_OS_WINDOWS) { if (SystemUtils.IS_OS_WINDOWS) {
return runPMDWindows(tempDir, reportFile, SOURCE_DIRECTORY_FLAG, sourceDirectory, RULESET_FLAG, ruleset, return runPMDWindows(tempDir, reportFile, SOURCE_DIRECTORY_FLAG, sourceDirectory, RULESET_FLAG, ruleset,
FORMAT_FLAG, FORMATTER, REPORTFILE_FLAG, reportFile.toAbsolutePath().toString()); FORMAT_FLAG, formatter, REPORTFILE_FLAG, reportFile.toAbsolutePath().toString());
} else { } else {
return runPMDUnix(tempDir, reportFile, SOURCE_DIRECTORY_FLAG, sourceDirectory, RULESET_FLAG, ruleset, return runPMDUnix(tempDir, reportFile, SOURCE_DIRECTORY_FLAG, sourceDirectory, RULESET_FLAG, ruleset,
FORMAT_FLAG, FORMATTER, REPORTFILE_FLAG, reportFile.toAbsolutePath().toString()); FORMAT_FLAG, formatter, REPORTFILE_FLAG, reportFile.toAbsolutePath().toString());
} }
} }
@ -129,4 +134,8 @@ public class PMDExecutor {
return runPMDUnix(tempDir, null, arguments); return runPMDUnix(tempDir, null, arguments);
} }
} }
public static boolean isJava7Test() {
return StringUtils.equals(System.getenv("JAVA_HOME"), System.getProperty("java7.home"));
}
} }

17
pom.xml
View File

@ -356,6 +356,11 @@
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M2</version> <version>3.0.0-M2</version>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId> <artifactId>maven-pmd-plugin</artifactId>
@ -652,7 +657,7 @@
<dependency> <dependency>
<groupId>com.beust</groupId> <groupId>com.beust</groupId>
<artifactId>jcommander</artifactId> <artifactId>jcommander</artifactId>
<version>1.72</version> <version>1.48</version> <!-- 1.48 is the latest version compatible with java7 -->
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.ow2.asm</groupId> <groupId>org.ow2.asm</groupId>
@ -699,7 +704,7 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId> <artifactId>commons-text</artifactId>
<version>1.6</version> <version>1.3</version> <!-- 1.3 is still compatible with java7 -->
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
@ -1064,10 +1069,6 @@
<module>pmd-plsql</module> <module>pmd-plsql</module>
<module>pmd-python</module> <module>pmd-python</module>
<module>pmd-ruby</module> <module>pmd-ruby</module>
<module>pmd-scala</module> <!-- deprecated -->
<module>pmd-scala-modules/pmd-scala-common</module>
<module>pmd-scala-modules/pmd-scala_2.13</module>
<module>pmd-scala-modules/pmd-scala_2.12</module>
<module>pmd-swift</module> <module>pmd-swift</module>
<module>pmd-test</module> <module>pmd-test</module>
<module>pmd-visualforce</module> <module>pmd-visualforce</module>
@ -1080,5 +1081,9 @@
<module>pmd-java8</module> <module>pmd-java8</module>
<module>pmd-doc</module> <module>pmd-doc</module>
<module>pmd-lang-test</module> <module>pmd-lang-test</module>
<module>pmd-scala</module> <!-- deprecated -->
<module>pmd-scala-modules/pmd-scala-common</module>
<module>pmd-scala-modules/pmd-scala_2.13</module>
<module>pmd-scala-modules/pmd-scala_2.12</module>
</modules> </modules>
</project> </project>