From 08c6ffd719f733f13b05edcd46762a0c9ed79cac Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 4 Jun 2020 12:27:07 +0200 Subject: [PATCH 1/2] [java] Auxclasspath in PMD CLI does not support relative file path Fixes #2549 --- docs/pages/pmd/userdocs/cli_reference.md | 4 +- docs/pages/release_notes.md | 3 ++ .../sourceforge/pmd/cli/PMDParameters.java | 6 ++- .../pmd/util/ClasspathClassLoader.java | 6 +-- .../sourceforge/pmd/ConfigurationTest.java | 44 +++++++++++++++++++ .../sourceforge/pmd/cli/auxclasspath-empty.cp | 4 ++ .../net/sourceforge/pmd/cli/auxclasspath.cp | 11 +++++ 7 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath-empty.cp create mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index a43c809081..743f5c3a15 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -40,7 +40,9 @@ The tool comes with a rather extensive help text, simply running with `-help`! {% include custom/cli_option_row.html options="-auxclasspath" option_arg="cp" description="Specifies the classpath for libraries used by the source code. - This is used to resolve types in source files. Alternatively, a `file://` URL + This is used to resolve types in source files. The platform specific path delimiter + (\":\" on Linux, \";\" on Windows) is used to separate the entries. + Alternatively, a single `file:` URL to a text file containing path elements on consecutive lines can be specified." languages="Java" %} diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..50dad76b7e 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* java + * [#2549](https://github.com/pmd/pmd/issues/2549): \[java] Auxclasspath in PMD CLI does not support relative file path + ### API Changes ### External Contributions diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index 218a40923d..b68cb336a3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -92,7 +92,11 @@ public class PMDParameters { private String language = null; @Parameter(names = "-auxclasspath", - description = "Specifies the classpath for libraries used by the source code. This is used by the type resolution. Alternatively, a 'file://' URL to a text file containing path elements on consecutive lines can be specified.") + description = "Specifies the classpath for libraries used by the source code. " + + "This is used by the type resolution. The platform specific path delimiter " + + "(\":\" on Linux, \";\" on Windows) is used to separate the entries. " + + "Alternatively, a single 'file:' URL to a text file containing path elements on consecutive lines " + + "can be specified.") private String auxclasspath; @Parameter(names = { "-failOnViolation", "--failOnViolation" }, arity = 1, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/ClasspathClassLoader.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/ClasspathClassLoader.java index e9b31a13cb..6c8148e274 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/ClasspathClassLoader.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/ClasspathClassLoader.java @@ -62,7 +62,7 @@ public class ClasspathClassLoader extends URLClassLoader { throw new IllegalArgumentException("classpath argument cannot be null"); } final List urls = new ArrayList<>(); - if (classpath.startsWith("file://")) { + if (classpath.startsWith("file:")) { // Treat as file URL addFileURLs(urls, new URL(classpath)); } else { @@ -87,7 +87,7 @@ public class ClasspathClassLoader extends URLClassLoader { while ((line = in.readLine()) != null) { LOG.log(Level.FINE, "Read classpath entry line: <{0}>", line); line = line.trim(); - if (line.length() > 0) { + if (line.length() > 0 && line.charAt(0) != '#') { LOG.log(Level.FINE, "Adding classpath entry: <{0}>", line); urls.add(createURLFromPath(line)); } @@ -97,7 +97,7 @@ public class ClasspathClassLoader extends URLClassLoader { private static URL createURLFromPath(String path) throws MalformedURLException { File file = new File(path); - return file.getAbsoluteFile().toURI().toURL(); + return file.getAbsoluteFile().toURI().normalize().toURL(); } @Override diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java index f1251cd25e..177e35ed95 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java @@ -12,10 +12,13 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Properties; +import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.cache.FileAnalysisCache; @@ -59,6 +62,47 @@ public class ConfigurationTest { configuration.getClassLoader()); } + @Test + public void auxClasspathWithRelativeFileEmpty() throws IOException { + String relativeFilePath = "src/test/resources/net/sourceforge/pmd/cli/auxclasspath-empty.cp"; + PMDConfiguration configuration = new PMDConfiguration(); + configuration.prependClasspath("file:" + relativeFilePath); + URL[] urls = ((ClasspathClassLoader) configuration.getClassLoader()).getURLs(); + Assert.assertEquals(0, urls.length); + } + + @Test + public void auxClasspathWithRelativeFileEmpty2() throws IOException { + String relativeFilePath = "./src/test/resources/net/sourceforge/pmd/cli/auxclasspath-empty.cp"; + PMDConfiguration configuration = new PMDConfiguration(); + configuration.prependClasspath("file:" + relativeFilePath); + URL[] urls = ((ClasspathClassLoader) configuration.getClassLoader()).getURLs(); + Assert.assertEquals(0, urls.length); + } + + @Test + public void auxClasspathWithRelativeFile() throws IOException, URISyntaxException { + String currentWorkingDirectory = new File("").getAbsolutePath() + "/"; + String relativeFilePath = "src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp"; + PMDConfiguration configuration = new PMDConfiguration(); + configuration.prependClasspath("file:" + relativeFilePath); + URL[] urls = ((ClasspathClassLoader) configuration.getClassLoader()).getURLs(); + URI[] uris = new URI[urls.length]; + for (int i = 0; i < urls.length; i++) { + uris[i] = urls[i].toURI(); + } + URI[] expectedUris = new URI[] { + URI.create("file:" + currentWorkingDirectory + "lib1.jar"), + URI.create("file:" + currentWorkingDirectory + "other/directory/lib2.jar"), + URI.create("file:/home/jondoe/libs/lib3.jar"), + URI.create("file:" + currentWorkingDirectory + "classes"), + URI.create("file:" + currentWorkingDirectory + "classes2"), + URI.create("file:/home/jondoe/classes"), + URI.create("file:" + currentWorkingDirectory), + }; + Assert.assertArrayEquals(expectedUris, uris); + } + @Test public void testRuleSets() { PMDConfiguration configuration = new PMDConfiguration(); diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath-empty.cp b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath-empty.cp new file mode 100644 index 0000000000..39eeac6911 --- /dev/null +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath-empty.cp @@ -0,0 +1,4 @@ +# this file is deliberately empty +# comments start with # + +# empty lines are ignored diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp new file mode 100644 index 0000000000..edfadcc7db --- /dev/null +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp @@ -0,0 +1,11 @@ +# relative paths here should be resolved relative to the current working directory - not relative to this file +lib1.jar +other/directory/lib2.jar +# absolute paths work as well +/home/jondoe/libs/lib3.jar +# also directories are possible +classes +classes2/ +/home/jondoe/classes +# relative current directory +. From 148391830861d1131ce2335d10f3836c8d505794 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 5 Jun 2020 10:31:01 +0200 Subject: [PATCH 2/2] [core] Fix tests under Windows, fix space handling in test Absolute paths under Windows use a drive letter... --- .../sourceforge/pmd/ConfigurationTest.java | 19 +++++++++++-------- .../net/sourceforge/pmd/cli/auxclasspath.cp | 2 ++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java index 177e35ed95..b88e95d8a9 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java @@ -82,7 +82,9 @@ public class ConfigurationTest { @Test public void auxClasspathWithRelativeFile() throws IOException, URISyntaxException { - String currentWorkingDirectory = new File("").getAbsolutePath() + "/"; + final String FILE_SCHEME = "file"; + + String currentWorkingDirectory = new File("").getAbsoluteFile().toURI().getPath(); String relativeFilePath = "src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp"; PMDConfiguration configuration = new PMDConfiguration(); configuration.prependClasspath("file:" + relativeFilePath); @@ -92,13 +94,14 @@ public class ConfigurationTest { uris[i] = urls[i].toURI(); } URI[] expectedUris = new URI[] { - URI.create("file:" + currentWorkingDirectory + "lib1.jar"), - URI.create("file:" + currentWorkingDirectory + "other/directory/lib2.jar"), - URI.create("file:/home/jondoe/libs/lib3.jar"), - URI.create("file:" + currentWorkingDirectory + "classes"), - URI.create("file:" + currentWorkingDirectory + "classes2"), - URI.create("file:/home/jondoe/classes"), - URI.create("file:" + currentWorkingDirectory), + new URI(FILE_SCHEME, null, currentWorkingDirectory + "lib1.jar", null), + new URI(FILE_SCHEME, null, currentWorkingDirectory + "other/directory/lib2.jar", null), + new URI(FILE_SCHEME, null, new File("/home/jondoe/libs/lib3.jar").getAbsoluteFile().toURI().getPath(), null), + new URI(FILE_SCHEME, null, currentWorkingDirectory + "classes", null), + new URI(FILE_SCHEME, null, currentWorkingDirectory + "classes2", null), + new URI(FILE_SCHEME, null, new File("/home/jondoe/classes").getAbsoluteFile().toURI().getPath(), null), + new URI(FILE_SCHEME, null, currentWorkingDirectory, null), + new URI(FILE_SCHEME, null, currentWorkingDirectory + "relative source dir/bar", null), }; Assert.assertArrayEquals(expectedUris, uris); } diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp index edfadcc7db..852cdf0bce 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/auxclasspath.cp @@ -9,3 +9,5 @@ classes2/ /home/jondoe/classes # relative current directory . +# a test with a space in the uri +relative source dir/bar