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.
(cherry picked from commit effe71ed54
)
This commit is contained in:
@@ -11,7 +11,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;
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -36,10 +38,14 @@ 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.
|
||||
* @param name String
|
||||
* 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
|
||||
* @return InputStream
|
||||
* @throws RuleSetNotFoundException
|
||||
*/
|
||||
@@ -52,10 +58,15 @@ public final class ResourceLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the ClassLoader passed in to attempt to load the
|
||||
* resource if it's not a File or a URL
|
||||
* @param name String
|
||||
* @param loader ClassLoader
|
||||
* 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
|
||||
* @param loader
|
||||
* ClassLoader
|
||||
* @return InputStream
|
||||
* @throws RuleSetNotFoundException
|
||||
*/
|
||||
@@ -83,8 +94,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
|
||||
}
|
||||
|
@@ -50,18 +50,19 @@ public class RuleSetFactoryTest {
|
||||
assertNotNull(rs.getRuleByName("TestRuleRef"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedReferences() throws Exception {
|
||||
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);
|
||||
@Test
|
||||
public void testExtendedReferences() throws Exception {
|
||||
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");
|
||||
// added by referencing a complete ruleset (TestRuleset1.xml)
|
||||
assertNotNull(rs.getRuleByName("MockRule1"));
|
||||
assertNotNull(rs.getRuleByName("MockRule2"));
|
||||
assertNotNull(rs.getRuleByName("MockRule3"));
|
||||
RuleSetFactory rsf = new RuleSetFactory();
|
||||
RuleSets rs = rsf.createRuleSets("net/sourceforge/pmd/rulesets/reference-ruleset.xml");
|
||||
// added by referencing a complete ruleset (TestRuleset1.xml)
|
||||
assertNotNull(rs.getRuleByName("MockRule1"));
|
||||
assertNotNull(rs.getRuleByName("MockRule2"));
|
||||
assertNotNull(rs.getRuleByName("MockRule3"));
|
||||
assertNotNull(rs.getRuleByName("TestRuleRef"));
|
||||
|
||||
// added by specific reference
|
||||
|
@@ -222,7 +222,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