diff --git a/.ci/jsoref-spellchecker/whitelist.words b/.ci/jsoref-spellchecker/whitelist.words
index 0cb45d0f24a4..479ba00a6dda 100644
--- a/.ci/jsoref-spellchecker/whitelist.words
+++ b/.ci/jsoref-spellchecker/whitelist.words
@@ -250,6 +250,7 @@ columnlimit
Combobox
commentsindentation
commerical
+commonutil
Compat
Compiletime
Comspace
diff --git a/.ci/pitest.sh b/.ci/pitest.sh
index e7239b6a39ef..0dfcabb417ba 100755
--- a/.ci/pitest.sh
+++ b/.ci/pitest.sh
@@ -282,9 +282,7 @@ pitest-tree-walker)
pitest-utils)
mvn -e -P$1 clean test org.pitest:pitest-maven:mutationCoverage;
declare -a ignoredItems=(
- "CommonUtil.java.html:
uri = configUrl.toURI(); | "
"CommonUtil.java.html: catch (final URISyntaxException ex) { | "
- "CommonUtil.java.html: } | "
"CommonUtil.java.html: throw new CheckstyleException(UNABLE_TO_FIND_EXCEPTION_PREFIX + filename, ex); | "
);
checkPitestReport "${ignoredItems[@]}"
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtil.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtil.java
index 71e8755dfd27..aae674f6ad80 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtil.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtil.java
@@ -507,8 +507,13 @@ public static URI getUriByFilename(String filename) throws CheckstyleException {
else {
// check to see if the file is in the classpath
try {
- final URL configUrl = CommonUtil.class
- .getResource(filename);
+ final URL configUrl;
+ if (filename.charAt(0) == '/') {
+ configUrl = CommonUtil.class.getResource(filename);
+ }
+ else {
+ configUrl = ClassLoader.getSystemResource(filename);
+ }
if (configUrl == null) {
throw new CheckstyleException(UNABLE_TO_FIND_EXCEPTION_PREFIX + filename);
}
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/internal/powermock/CommonUtilPowerTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/internal/powermock/CommonUtilPowerTest.java
index b967b67a9002..87d3a8148471 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/powermock/CommonUtilPowerTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/internal/powermock/CommonUtilPowerTest.java
@@ -49,7 +49,7 @@ public void testLoadSuppressionsUriSyntaxException() throws Exception {
when(configUrl.toURI()).thenThrow(URISyntaxException.class);
mockStatic(CommonUtil.class, Mockito.CALLS_REAL_METHODS);
- final String fileName = "suppressions_none.xml";
+ final String fileName = "/suppressions_none.xml";
when(CommonUtil.class.getResource(fileName)).thenReturn(configUrl);
try {
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/utils/CommonUtilTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/utils/CommonUtilTest.java
index b07c39eb96ba..6f6ac78f615b 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/utils/CommonUtilTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/utils/CommonUtilTest.java
@@ -20,25 +20,37 @@
package com.puppycrawl.tools.checkstyle.utils;
import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.util.Dictionary;
import java.util.regex.Pattern;
+import org.apache.commons.io.IOUtils;
import org.junit.Test;
+import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
-public class CommonUtilTest {
+public class CommonUtilTest extends AbstractPathTestSupport {
/** After appending to path produces equivalent, but denormalized path. */
private static final String PATH_DENORMALIZER = "/levelDown/.././";
@@ -440,6 +452,42 @@ public void testIsIntNull() {
CommonUtil.isInt(null));
}
+ @Test
+ public void testGetUriByFilenameFindsAbsoluteResourceOnClasspath() throws Exception {
+ final String filename =
+ "/" + getPackageLocation() + "/InputCommonUtilTest_empty_checks.xml";
+ final URI uri = CommonUtil.getUriByFilename(filename);
+ assertThat("URI is null for: " + filename, uri, is(not(nullValue())));
+ }
+
+ @Test
+ public void testGetUriByFilenameFindsRelativeResourceOnClasspath() throws Exception {
+ final String filename =
+ getPackageLocation() + "/InputCommonUtilTest_empty_checks.xml";
+ final URI uri = CommonUtil.getUriByFilename(filename);
+ assertThat("URI is null for: " + filename, uri, is(not(nullValue())));
+ }
+
+ @Test
+ public void testGetUriByFilenameFindsResourceRelativeToRootClasspath() throws Exception {
+ final String filename = "commonutil/InputCommonUtilTest_resource.txt";
+ final URI uri = CommonUtil.getUriByFilename(filename);
+ assertThat("URI is null for: " + filename, uri, is(not(nullValue())));
+ assertThat("URI contains com/puppycrawl/tools/checkstyle/utils",
+ uri.toString(), not(containsString("com/puppycrawl/tools/checkstyle/utils")));
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try (InputStream in = uri.toURL().openStream()) {
+ IOUtils.copy(in, out);
+ }
+ assertThat("Content mismatches for: " + uri,
+ new String(out.toByteArray(), StandardCharsets.UTF_8), startsWith("good"));
+ }
+
+ @Override
+ protected String getPackageLocation() {
+ return "com/puppycrawl/tools/checkstyle/utils/commonutil";
+ }
+
private static class TestCloseable implements Closeable {
private boolean closed;
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/utils/commonutil/InputCommonUtilTest_empty_checks.xml b/src/test/resources/com/puppycrawl/tools/checkstyle/utils/commonutil/InputCommonUtilTest_empty_checks.xml
new file mode 100644
index 000000000000..8c7f885f0e2d
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/utils/commonutil/InputCommonUtilTest_empty_checks.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/utils/commonutil/InputCommonUtilTest_resource.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/utils/commonutil/InputCommonUtilTest_resource.txt
new file mode 100644
index 000000000000..67be85f12744
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/utils/commonutil/InputCommonUtilTest_resource.txt
@@ -0,0 +1 @@
+bad
diff --git a/src/test/resources/commonutil/InputCommonUtilTest_resource.txt b/src/test/resources/commonutil/InputCommonUtilTest_resource.txt
new file mode 100644
index 000000000000..12799ccbe7ce
--- /dev/null
+++ b/src/test/resources/commonutil/InputCommonUtilTest_resource.txt
@@ -0,0 +1 @@
+good