forked from phoedos/pmd
Modify ResourceLoader to close underlying JarFile if using JarURLConnection to avoid open file leaks. Clarify on JavaDoc that caller must close the returned InputStream. Minor test usage cleanups.
This commit is contained in:
@ -10,7 +10,9 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
import net.sourceforge.pmd.RuleSetNotFoundException;
|
||||
|
||||
@ -41,6 +43,8 @@ public final class ResourceLoader {
|
||||
* Method to find a file, first by finding it as a file (either by the
|
||||
* absolute or relative path), then as a URL, and then finally seeing if it
|
||||
* is on the classpath.
|
||||
* <p>
|
||||
* Caller is responsible for closing the {@link InputStream}.
|
||||
*
|
||||
* @param name
|
||||
* String
|
||||
@ -59,6 +63,8 @@ public final class ResourceLoader {
|
||||
/**
|
||||
* Uses the ClassLoader passed in to attempt to load the resource if it's
|
||||
* not a File or a URL
|
||||
* <p>
|
||||
* Caller is responsible for closing the {@link InputStream}.
|
||||
*
|
||||
* @param name
|
||||
* String
|
||||
@ -91,8 +97,30 @@ public final class ResourceLoader {
|
||||
if (resource == null) {
|
||||
// Don't throw RuleSetNotFoundException, keep API compatibility
|
||||
return null;
|
||||
} else {
|
||||
final URLConnection connection = resource.openConnection();
|
||||
final InputStream inputStream = connection.getInputStream();
|
||||
if (connection instanceof JarURLConnection) {
|
||||
// Wrap the InputStream to also close the underlying JarFile if from a JarURLConnection.
|
||||
// See https://github.com/pmd/pmd/issues/337
|
||||
return new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
if (connection instanceof JarURLConnection) {
|
||||
((JarURLConnection) connection).getJarFile().close();
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return inputStream;
|
||||
}
|
||||
}
|
||||
return resource.openStream();
|
||||
} catch (IOException e1) {
|
||||
// Ignored
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public class RuleSetFactoryTest {
|
||||
InputStream in = ResourceLoader.loadResourceAsStream("net/sourceforge/pmd/rulesets/reference-ruleset.xml",
|
||||
this.getClass().getClassLoader());
|
||||
Assert.assertNotNull("Test ruleset not found - can't continue with test!", in);
|
||||
in.close();
|
||||
|
||||
RuleSetFactory rsf = new RuleSetFactory();
|
||||
RuleSets rs = rsf.createRuleSets("net/sourceforge/pmd/rulesets/reference-ruleset.xml");
|
||||
|
@ -229,7 +229,9 @@ public abstract class AbstractRuleSetFactoryTest {
|
||||
List<String> ruleSetFileNames = new ArrayList<>();
|
||||
try {
|
||||
Properties properties = new Properties();
|
||||
properties.load(ResourceLoader.loadResourceAsStream("rulesets/" + language + "/rulesets.properties"));
|
||||
try (InputStream is = ResourceLoader.loadResourceAsStream("rulesets/" + language + "/rulesets.properties")) {
|
||||
properties.load(is);
|
||||
}
|
||||
String fileNames = properties.getProperty("rulesets.filenames");
|
||||
StringTokenizer st = new StringTokenizer(fileNames, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
|
Reference in New Issue
Block a user