Merge branch 'pr-1489'
This commit is contained in:
@ -38,6 +38,7 @@ This means, you can use CPD to find duplicated code in your Kotlin projects.
|
||||
* [#1341](https://github.com/pmd/pmd/issues/1341): \[doc] Documentation Error with Regex Properties
|
||||
* [#1468](https://github.com/pmd/pmd/issues/1468): \[doc] Missing escaping leads to XSS
|
||||
* [#1471](https://github.com/pmd/pmd/issues/1471): \[core] XMLRenderer: ProcessingErrors from exceptions without a message missing
|
||||
* [#1477](https://github.com/pmd/pmd/issues/1477): \[core] Analysis cache fails with wildcard classpath entries
|
||||
* java
|
||||
* [#1460](https://github.com/pmd/pmd/issues/1460): \[java] Intermittent PMD failure : PMD processing errors while no violations reported
|
||||
* java-bestpractices
|
||||
|
@ -26,6 +26,7 @@ import java.util.logging.Logger;
|
||||
import java.util.zip.Adler32;
|
||||
import java.util.zip.CheckedInputStream;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import net.sourceforge.pmd.PMDVersion;
|
||||
@ -153,28 +154,48 @@ public abstract class AbstractAnalysisCache implements AnalysisCache {
|
||||
ruleMapper.initialize(ruleSets);
|
||||
}
|
||||
|
||||
private static boolean isClassPathWildcard(String entry) {
|
||||
return entry.endsWith("/*") || entry.endsWith("\\*");
|
||||
}
|
||||
|
||||
private URL[] getClassPathEntries() {
|
||||
final String classpath = System.getProperty("java.class.path");
|
||||
final String[] classpathEntries = classpath.split(File.pathSeparator);
|
||||
final List<URL> entries = new ArrayList<>();
|
||||
|
||||
final SimpleFileVisitor<Path> fileVisitor = new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(final Path file,
|
||||
final BasicFileAttributes attrs) throws IOException {
|
||||
if (!attrs.isSymbolicLink()) { // Broken link that can't be followed
|
||||
entries.add(file.toUri().toURL());
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
};
|
||||
final SimpleFileVisitor<Path> jarFileVisitor = new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(final Path file,
|
||||
final BasicFileAttributes attrs) throws IOException {
|
||||
String extension = FilenameUtils.getExtension(file.toString());
|
||||
if ("jar".equalsIgnoreCase(extension)) {
|
||||
fileVisitor.visitFile(file, attrs);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
for (final String entry : classpathEntries) {
|
||||
final File f = new File(entry);
|
||||
if (f.isFile()) {
|
||||
if (isClassPathWildcard(entry)) {
|
||||
Files.walkFileTree(new File(entry.substring(0, entry.length() - 1)).toPath(),
|
||||
EnumSet.of(FileVisitOption.FOLLOW_LINKS), 1, jarFileVisitor);
|
||||
} else if (f.isFile()) {
|
||||
entries.add(f.toURI().toURL());
|
||||
} else {
|
||||
Files.walkFileTree(f.toPath(), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
|
||||
new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(final Path file,
|
||||
final BasicFileAttributes attrs) throws IOException {
|
||||
if (!attrs.isSymbolicLink()) { // Broken link that can't be followed
|
||||
entries.add(file.toUri().toURL());
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
fileVisitor);
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
|
@ -16,6 +16,7 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
@ -254,7 +255,51 @@ public class FileAnalysisCacheTest {
|
||||
assertFalse("Cache believes cache is up to date when a classpath file changed",
|
||||
reloadedCache.isUpToDate(sourceFile));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testWildcardClasspath() throws MalformedURLException, IOException {
|
||||
final RuleSets rs = mock(RuleSets.class);
|
||||
final ClassLoader cl = mock(ClassLoader.class);
|
||||
setupCacheWithFiles(newCacheFile, rs, cl, sourceFile);
|
||||
|
||||
// Prepare two jar files
|
||||
final File classpathJar1 = tempFolder.newFile("mylib1.jar");
|
||||
Files.write(classpathJar1.toPath(), "content of mylib1.jar".getBytes(StandardCharsets.UTF_8));
|
||||
final File classpathJar2 = tempFolder.newFile("mylib2.jar");
|
||||
Files.write(classpathJar2.toPath(), "content of mylib2.jar".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
System.setProperty("java.class.path", System.getProperty("java.class.path") + File.pathSeparator + tempFolder.getRoot().getAbsolutePath() + "/*");
|
||||
|
||||
final FileAnalysisCache reloadedCache = new FileAnalysisCache(newCacheFile);
|
||||
reloadedCache.checkValidity(rs, cl);
|
||||
assertFalse("Cache believes cache is up to date when the classpath changed",
|
||||
reloadedCache.isUpToDate(sourceFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildcardClasspathContentsChangeInvalidatesCache() throws MalformedURLException, IOException {
|
||||
final RuleSets rs = mock(RuleSets.class);
|
||||
final ClassLoader cl = mock(ClassLoader.class);
|
||||
|
||||
// Prepare two jar files
|
||||
final File classpathJar1 = tempFolder.newFile("mylib1.jar");
|
||||
Files.write(classpathJar1.toPath(), "content of mylib1.jar".getBytes(StandardCharsets.UTF_8));
|
||||
final File classpathJar2 = tempFolder.newFile("mylib2.jar");
|
||||
Files.write(classpathJar2.toPath(), "content of mylib2.jar".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
System.setProperty("java.class.path", System.getProperty("java.class.path") + File.pathSeparator + tempFolder.getRoot().getAbsolutePath() + "/*");
|
||||
|
||||
setupCacheWithFiles(newCacheFile, rs, cl, sourceFile);
|
||||
|
||||
// Change one file's contents
|
||||
Files.write(Paths.get(classpathJar2.getAbsolutePath()), "some other text".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
final FileAnalysisCache reloadedCache = new FileAnalysisCache(newCacheFile);
|
||||
reloadedCache.checkValidity(rs, cl);
|
||||
assertFalse("Cache believes cache is up to date when the classpath changed",
|
||||
reloadedCache.isUpToDate(sourceFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnknownFileIsNotUpToDate() throws IOException {
|
||||
final FileAnalysisCache cache = new FileAnalysisCache(newCacheFile);
|
||||
|
Reference in New Issue
Block a user