() {
+ @Override
+ public int compare(File o1, File o2) {
+ return o1.getPath().compareToIgnoreCase(o2.getPath());
+ }
+ });
for (File tmp : candidates) {
if (tmp.isDirectory()) {
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java
index 38484692ed..c4aec51b09 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java
@@ -23,7 +23,6 @@ import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.annotation.InternalApi;
@@ -183,7 +182,7 @@ public final class FileUtil {
* @throws IOException if the file couldn't be read
*/
public static String readFilelist(File filelist) throws IOException {
- String filePaths = FileUtils.readFileToString(filelist);
+ String filePaths = IOUtil.readFileToString(filelist);
filePaths = StringUtils.trimToEmpty(filePaths);
filePaths = filePaths.replaceAll("\\r?\\n", ",");
filePaths = filePaths.replaceAll(",+", ",");
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java
index 09a162bc1a..61129d4431 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java
@@ -7,21 +7,30 @@ package net.sourceforge.pmd.util;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
+import java.io.FilterInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.List;
+import java.util.Objects;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -36,6 +45,8 @@ import net.sourceforge.pmd.annotation.InternalApi;
@Deprecated
public final class IOUtil {
+ private static final int BUFFER_SIZE = 8192;
+
private IOUtil() {
}
@@ -120,7 +131,7 @@ public final class IOUtil {
public static void tryCloseClassLoader(ClassLoader classLoader) {
if (classLoader instanceof Closeable) {
- IOUtils.closeQuietly((Closeable) classLoader);
+ closeQuietly((Closeable) classLoader);
}
}
@@ -169,4 +180,308 @@ public final class IOUtil {
throw pendingException;
}
}
+
+ public static void closeQuietly(Closeable closeable) {
+ try {
+ closeable.close();
+ } catch (IOException ignored) {
+ // ignored
+ }
+ }
+
+ public static byte[] toByteArray(InputStream stream) throws IOException {
+ byte[] result = new byte[0];
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int count = stream.read(buffer);
+ while (count > -1) {
+ byte[] newResult = new byte[result.length + count];
+ System.arraycopy(result, 0, newResult, 0, result.length);
+ System.arraycopy(buffer, 0, newResult, result.length, count);
+ result = newResult;
+ count = stream.read(buffer);
+ }
+ return result;
+ }
+
+ public static long skipFully(InputStream stream, long n) throws IOException {
+ if (n < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ long bytesToSkip = n;
+ byte[] buffer = new byte[(int) Math.min(BUFFER_SIZE, bytesToSkip)];
+ while (bytesToSkip > 0) {
+ int count = stream.read(buffer, 0, (int) Math.min(BUFFER_SIZE, bytesToSkip));
+ if (count < 0) {
+ // reached eof
+ break;
+ }
+ bytesToSkip -= count;
+ }
+ return n - bytesToSkip;
+ }
+
+ public static String normalizePath(String path) {
+ Path path1 = Paths.get(path);
+ path1.isAbsolute();
+ String normalized = path1.normalize().toString();
+ if (normalized.contains("." + File.separator) || normalized.contains(".." + File.separator) || "".equals(normalized)) {
+ return null;
+ }
+ return normalized;
+ }
+
+ public static boolean equalsNormalizedPaths(String path1, String path2) {
+ return Objects.equals(normalizePath(path1), normalizePath(path2));
+ }
+
+ public static String getFilenameExtension(String name) {
+ String filename = Paths.get(name).getFileName().toString();
+ int dot = filename.lastIndexOf('.');
+ if (dot > -1) {
+ return filename.substring(dot + 1);
+ }
+ return "";
+ }
+
+ public static String getFilenameBase(String name) {
+ String filename = Paths.get(name).getFileName().toString();
+ int dot = filename.lastIndexOf('.');
+ if (dot > -1) {
+ return filename.substring(0, dot);
+ }
+ return filename;
+ }
+
+ public static void copy(InputStream from, OutputStream to) throws IOException {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int count = from.read(buffer);
+ while (count > -1) {
+ to.write(buffer, 0, count);
+ count = from.read(buffer);
+ }
+ }
+
+ public static void copy(Reader from, Writer to) throws IOException {
+ char[] buffer = new char[BUFFER_SIZE];
+ int count = from.read(buffer);
+ while (count > -1) {
+ to.write(buffer, 0, count);
+ count = from.read(buffer);
+ }
+ }
+
+ public static String readFileToString(File file) throws IOException {
+ return readFileToString(file, Charset.defaultCharset());
+ }
+
+ public static String readFileToString(File file, Charset charset) throws IOException {
+ byte[] bytes = Files.readAllBytes(file.toPath());
+ return charset.decode(ByteBuffer.wrap(bytes)).toString();
+ }
+
+ public static String readToString(Reader reader) throws IOException {
+ StringBuilder sb = new StringBuilder(BUFFER_SIZE);
+ char[] buffer = new char[BUFFER_SIZE];
+ int count = reader.read(buffer);
+ while (count > -1) {
+ sb.append(buffer, 0, count);
+ count = reader.read(buffer);
+ }
+ return sb.toString();
+ }
+
+ public static String readToString(InputStream stream, Charset charset) throws IOException {
+ byte[] bytes = toByteArray(stream);
+ return charset.decode(ByteBuffer.wrap(bytes)).toString();
+ }
+
+ public static InputStream fromReader(Reader reader) throws IOException {
+ class ReaderInputStream extends InputStream {
+ private final Reader reader;
+ private final CharBuffer charBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ private final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+ private final CharsetEncoder encoder;
+
+ private boolean eof;
+
+ ReaderInputStream(Reader reader) {
+ this.reader = reader;
+ encoder = Charset.defaultCharset().newEncoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ charBuffer.clear();
+ byteBuffer.clear();
+ byteBuffer.flip(); // byte buffer is empty at the beginning, no bytes read yet
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (!byteBuffer.hasRemaining()) {
+ if (charBuffer.hasRemaining() && !eof) {
+ int count = reader.read(charBuffer);
+ eof = count == -1;
+ }
+ byteBuffer.clear();
+ charBuffer.flip();
+ encoder.encode(charBuffer, byteBuffer, eof);
+ byteBuffer.flip();
+ charBuffer.flip();
+ }
+
+ if (byteBuffer.hasRemaining()) {
+ return byteBuffer.get();
+ }
+
+ return -1;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return byteBuffer.remaining();
+ }
+
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ }
+ }
+
+ return new ReaderInputStream(reader);
+ }
+
+ public static OutputStream fromWriter(Writer writer, String encoding) throws UnsupportedCharsetException {
+ class WriterOutputStream extends OutputStream {
+ private final Writer writer;
+ private final CharsetDecoder decoder;
+ private final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
+ private final CharBuffer charBuffer = CharBuffer.allocate(BUFFER_SIZE);
+
+ WriterOutputStream(Writer writer, String encoding) throws UnsupportedCharsetException {
+ this.writer = writer;
+ Charset charset = Charset.forName(encoding);
+ decoder = charset.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ byteBuffer.clear();
+ charBuffer.clear();
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ if (!byteBuffer.hasRemaining()) {
+ decodeByteBuffer(false);
+ }
+ byteBuffer.put((byte) b);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ decodeByteBuffer(false);
+ }
+
+ private void decodeByteBuffer(boolean isClosing) throws IOException {
+ byteBuffer.flip();
+ charBuffer.clear();
+ decoder.decode(byteBuffer, charBuffer, isClosing);
+ writer.write(charBuffer.array(), 0, charBuffer.position());
+ writer.flush();
+ byteBuffer.compact();
+ }
+
+ @Override
+ public void close() throws IOException {
+ flush();
+ decodeByteBuffer(true);
+ writer.close();
+ }
+ }
+
+ return new WriterOutputStream(writer, encoding);
+ }
+
+ /**
+ *
+ * Input stream that skips an optional byte order mark at the beginning
+ * of the stream. Whether the stream had a byte order mark (encoded in either UTF-8,
+ * UTF-16LE or UTF-16BE) can be checked with {@link #hasBom()}. The corresponding
+ * charset can be retrieved with {@link #getBomCharsetName()}.
+ *
+ *
+ *
+ * If the stream didn't had a BOM, then no bytes are skipped.
+ *
+ */
+ public static class BomAwareInputStream extends FilterInputStream {
+
+ private byte[] begin;
+ int beginIndex;
+
+ private String charset;
+
+ public BomAwareInputStream(InputStream in) {
+ super(in);
+ begin = determineBom();
+ }
+
+ private byte[] determineBom() {
+ byte[] bytes = new byte[3];
+ try {
+ int count = in.read(bytes);
+ if (count == 3 && bytes[0] == (byte) 0xef && bytes[1] == (byte) 0xbb && bytes[2] == (byte) 0xbf) {
+ charset = StandardCharsets.UTF_8.name();
+ return new byte[0]; // skip all 3 bytes
+ } else if (count >= 2 && bytes[0] == (byte) 0xfe && bytes[1] == (byte) 0xff) {
+ charset = StandardCharsets.UTF_16BE.name();
+ return new byte[] { bytes[2] };
+ } else if (count >= 2 && bytes[0] == (byte) 0xff && bytes[1] == (byte) 0xfe) {
+ charset = StandardCharsets.UTF_16LE.name();
+ return new byte[] { bytes[2] };
+ } else if (count == 3) {
+ return bytes;
+ }
+
+ if (count < 0) {
+ return new byte[0];
+ }
+
+ byte[] read = new byte[count];
+ for (int i = 0; i < count; i++) {
+ read[i] = bytes[i];
+ }
+ return read;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (beginIndex < begin.length) {
+ return begin[beginIndex++];
+ }
+ return super.read();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (beginIndex < begin.length) {
+ int count = 0;
+ for (; count < len && beginIndex < begin.length; beginIndex++) {
+ b[off + count] = begin[beginIndex];
+ count++;
+ }
+ return count;
+ }
+ return super.read(b, off, len);
+ }
+
+ public boolean hasBom() {
+ return charset != null;
+ }
+
+ public String getBomCharsetName() {
+ return charset;
+ }
+ }
}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java
index ec21c09f4b..fe530ae40c 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java
@@ -8,8 +8,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
-import org.apache.commons.io.input.ReaderInputStream;
-
+import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.datasource.internal.AbstractDataSource;
/**
@@ -50,7 +49,7 @@ public class ReaderDataSource extends AbstractDataSource {
*/
@Override
public InputStream getInputStream() throws IOException {
- return new ReaderInputStream(reader);
+ return IOUtil.fromReader(reader);
}
/**
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java
index 0914045572..fa48c86698 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java
@@ -22,9 +22,9 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
-import org.apache.commons.io.IOUtils;
import org.junit.Test;
+import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.ResourceLoader;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
@@ -123,7 +123,7 @@ public class RuleSetReferenceIdTest {
assertRuleSetReferenceId(true, rulesetUrl, true, null, rulesetUrl, ruleSetReferenceId);
try (InputStream inputStream = ruleSetReferenceId.getInputStream(new ResourceLoader())) {
- String loaded = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ String loaded = IOUtil.readToString(inputStream, StandardCharsets.UTF_8);
assertEquals("xyz", loaded);
}
@@ -139,8 +139,8 @@ public class RuleSetReferenceIdTest {
String path = "/profiles/export?format=pmd&language=java&name=Sonar%2520way";
String completePath = path + "/DummyBasicMockRule";
String hostpart = "http://localhost:" + wireMockRule.port();
- String basicRuleSet = IOUtils
- .toString(RuleSetReferenceId.class.getResourceAsStream("/rulesets/dummy/basic.xml"), StandardCharsets.UTF_8);
+ String basicRuleSet = IOUtil
+ .readToString(RuleSetReferenceId.class.getResourceAsStream("/rulesets/dummy/basic.xml"), StandardCharsets.UTF_8);
stubFor(head(urlEqualTo(completePath)).willReturn(aResponse().withStatus(404)));
stubFor(head(urlEqualTo(path)).willReturn(aResponse().withStatus(200).withHeader("Content-type", "text/xml")));
@@ -152,7 +152,7 @@ public class RuleSetReferenceIdTest {
ruleSetReferenceId);
try (InputStream inputStream = ruleSetReferenceId.getInputStream(new ResourceLoader())) {
- String loaded = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ String loaded = IOUtil.readToString(inputStream, StandardCharsets.UTF_8);
assertEquals(basicRuleSet, loaded);
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java
index 503b8d0c98..bb28775238 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java
@@ -30,7 +30,6 @@ import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import org.apache.commons.io.FilenameUtils;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.junit.Test;
@@ -45,6 +44,7 @@ import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.rule.RuleReference;
import net.sourceforge.pmd.lang.rule.RuleTargetSelector;
+import net.sourceforge.pmd.util.IOUtil;
public class RuleSetTest {
@@ -523,7 +523,7 @@ public class RuleSetTest {
assertThat(error.getMsg(), containsString("java.lang.IllegalStateException: Test exception while applying rule\n"));
assertThat(error.getMsg(), containsString("Rule applied on node=dummyRootNode[@Image=Foo]"));
assertThat(error.getError().getCause(), instanceOf(IllegalStateException.class));
- assertThat(FilenameUtils.normalize(error.getFile(), true), equalTo("samplefile.dummy"));
+ assertThat(IOUtil.normalizePath(error.getFile()), equalTo("samplefile.dummy"));
assertThat(report.getViolations(), hasSize(1));
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java
index 6e2ae33f8f..4fa4b5fd8e 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java
@@ -11,7 +11,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.IOUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildFileRule;
import org.junit.AfterClass;
@@ -24,6 +23,8 @@ import org.junit.rules.TestRule;
import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration;
+import net.sourceforge.pmd.util.IOUtil;
+
public class PMDTaskTest {
@Rule
@@ -89,7 +90,7 @@ public class PMDTaskTest {
buildRule.executeTarget("testWithShortFilenames");
try (InputStream in = new FileInputStream("target/pmd-ant-test.txt")) {
- String actual = IOUtils.toString(in, StandardCharsets.UTF_8);
+ String actual = IOUtil.readToString(in, StandardCharsets.UTF_8);
// remove any trailing newline
actual = actual.trim();
Assert.assertEquals("sample.dummy:1:\tSampleXPathRule:\tTest Rule 2", actual);
@@ -102,11 +103,11 @@ public class PMDTaskTest {
try (InputStream in = new FileInputStream("target/pmd-ant-xml.xml");
InputStream expectedStream = PMDTaskTest.class.getResourceAsStream("xml/expected-pmd-ant-xml.xml")) {
- String actual = IOUtils.toString(in, StandardCharsets.UTF_8);
+ String actual = IOUtil.readToString(in, StandardCharsets.UTF_8);
actual = actual.replaceFirst("timestamp=\"[^\"]+\"", "timestamp=\"\"");
actual = actual.replaceFirst("\\.xsd\" version=\"[^\"]+\"", ".xsd\" version=\"\"");
- String expected = IOUtils.toString(expectedStream, StandardCharsets.UTF_8);
+ String expected = IOUtil.readToString(expectedStream, StandardCharsets.UTF_8);
expected = expected.replaceFirst("timestamp=\"[^\"]+\"", "timestamp=\"\"");
expected = expected.replaceFirst("\\.xsd\" version=\"[^\"]+\"", ".xsd\" version=\"\"");
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java
index 47106eb626..f2e95e9205 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java
@@ -20,7 +20,6 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
-import org.apache.commons.io.IOUtils;
import org.hamcrest.Matcher;
import org.junit.AfterClass;
import org.junit.Before;
@@ -34,6 +33,7 @@ import org.junit.rules.TemporaryFolder;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.PMD.StatusCode;
import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration;
+import net.sourceforge.pmd.util.IOUtil;
/**
*
@@ -135,7 +135,7 @@ public class CoreCliTest {
runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET, "--report-file", reportFile, "--debug");
assertTrue("Report file should have been created", Files.exists(reportFile));
- String reportText = IOUtils.toString(Files.newBufferedReader(reportFile, StandardCharsets.UTF_8));
+ String reportText = IOUtil.readToString(Files.newBufferedReader(reportFile, StandardCharsets.UTF_8));
assertThat(reportText, not(containsStringIgnoringCase("error")));
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java
index 5c21740f85..74604cc10a 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java
@@ -7,11 +7,11 @@ package net.sourceforge.pmd.cpd;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.nio.file.Paths;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.apache.commons.io.FilenameUtils;
import org.junit.Test;
public class CPDFilelistTest {
@@ -28,7 +28,7 @@ public class CPDFilelistTest {
assertEquals(2, paths.size());
Set simpleNames = new HashSet<>();
for (String path : paths) {
- simpleNames.add(FilenameUtils.getName(path));
+ simpleNames.add(Paths.get(path).getFileName().toString());
}
assertTrue(simpleNames.contains("anotherfile.dummy"));
assertTrue(simpleNames.contains("somefile.dummy"));
@@ -46,7 +46,7 @@ public class CPDFilelistTest {
assertEquals(2, paths.size());
Set simpleNames = new HashSet<>();
for (String path : paths) {
- simpleNames.add(FilenameUtils.getName(path));
+ simpleNames.add(Paths.get(path).getFileName().toString());
}
assertTrue(simpleNames.contains("anotherfile.dummy"));
assertTrue(simpleNames.contains("somefile.dummy"));
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java
index 085475f8d0..af8d5ada20 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java
@@ -17,10 +17,11 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
-import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
+import net.sourceforge.pmd.util.IOUtil;
+
public class CpdXsltTest {
/* Sample ant build.xml file. Run with "ant cpdxsl".
@@ -49,7 +50,7 @@ public class CpdXsltTest {
transformer.setErrorListener(errorListener);
transformer.transform(cpdReport, result);
- String expected = IOUtils.toString(CpdXsltTest.class.getResourceAsStream("ExpectedCpdHtmlReport.html"), StandardCharsets.UTF_8);
+ String expected = IOUtil.readToString(CpdXsltTest.class.getResourceAsStream("ExpectedCpdHtmlReport.html"), StandardCharsets.UTF_8);
Assert.assertEquals(expected, result.getWriter().toString());
Assert.assertTrue("XSLT errors occured: " + errorListener, errorListener.hasNoErrors());
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java
index ece529938d..d578dec542 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java
@@ -16,12 +16,13 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import net.sourceforge.pmd.util.IOUtil;
+
public class DocumentFileTest {
private static final String FILE_PATH = "psvm.java";
@@ -51,8 +52,8 @@ public class DocumentFileTest {
@Test
public void shouldPreserveNewlines() throws IOException {
- final String testFileContent = IOUtils.toString(
- DocumentFileTest.class.getResource("ShouldPreserveNewlines.java"), StandardCharsets.UTF_8);
+ final String testFileContent = IOUtil.readToString(
+ DocumentFileTest.class.getResourceAsStream("ShouldPreserveNewlines.java"), StandardCharsets.UTF_8);
writeContentToTemporaryFile(testFileContent);
try (DocumentFile documentFile = new DocumentFile(temporaryFile, StandardCharsets.UTF_8)) {
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java
index 884e82ce99..f84aa9e635 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java
@@ -13,8 +13,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -32,6 +30,7 @@ import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
import net.sourceforge.pmd.reporting.FileAnalysisListener;
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
+import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.datasource.DataSource;
public abstract class AbstractRendererTest {
@@ -126,7 +125,7 @@ public abstract class AbstractRendererTest {
*/
protected String readFile(String relativePath) {
try (InputStream in = getClass().getResourceAsStream(relativePath)) {
- return IOUtils.toString(in, StandardCharsets.UTF_8);
+ return IOUtil.readToString(in, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -221,7 +220,7 @@ public abstract class AbstractRendererTest {
throw new AssertionError(e);
}
- return FileUtils.readFileToString(file, expectedEncoding);
+ return IOUtil.readFileToString(file, expectedEncoding);
}
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java
index 9faefb055f..858826c5a9 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java
@@ -18,7 +18,6 @@ import net.sourceforge.pmd.Report;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.reporting.FileAnalysisListener;
-
public class SarifRendererTest extends AbstractRendererTest {
@org.junit.Rule
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java
index aa6a10f28f..ec81f1bd5a 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java
@@ -12,7 +12,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
@@ -33,6 +32,7 @@ import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.DummyNode.DummyRootNode;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
+import net.sourceforge.pmd.util.IOUtil;
public class XMLRendererTest extends AbstractRendererTest {
@Rule // Restores system properties after test
@@ -169,7 +169,7 @@ public class XMLRendererTest extends AbstractRendererTest {
renderer.flush();
try (FileInputStream input = new FileInputStream(reportFile)) {
- return IOUtils.toString(input, expectedCharset);
+ return IOUtil.readToString(input, expectedCharset);
}
}
}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java
index f7e964be7f..e4fc711fb8 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java
@@ -14,7 +14,6 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.regex.Pattern;
-import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -28,6 +27,7 @@ import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
+import net.sourceforge.pmd.util.IOUtil;
public class YAHTMLRendererTest extends AbstractRendererTest {
@@ -75,8 +75,8 @@ public class YAHTMLRendererTest extends AbstractRendererTest {
for (String file : htmlFiles) {
try (FileInputStream in = new FileInputStream(new File(outputDir, file));
InputStream expectedIn = YAHTMLRendererTest.class.getResourceAsStream("yahtml/" + file)) {
- String data = IOUtils.toString(in, StandardCharsets.UTF_8);
- String expected = normalizeLineSeparators(IOUtils.toString(expectedIn, StandardCharsets.UTF_8));
+ String data = IOUtil.readToString(in, StandardCharsets.UTF_8);
+ String expected = normalizeLineSeparators(IOUtil.readToString(expectedIn, StandardCharsets.UTF_8));
assertEquals("File " + file + " is different", expected, data);
}
@@ -84,8 +84,8 @@ public class YAHTMLRendererTest extends AbstractRendererTest {
}
private static String normalizeLineSeparators(String s) {
- return s.replaceAll(Pattern.quote(IOUtils.LINE_SEPARATOR_WINDOWS), IOUtils.LINE_SEPARATOR_UNIX)
- .replaceAll(Pattern.quote(IOUtils.LINE_SEPARATOR_UNIX), PMD.EOL);
+ return s.replaceAll(Pattern.quote("\r\n"), "\n")
+ .replaceAll(Pattern.quote("\n"), PMD.EOL);
}
@Override
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java
new file mode 100644
index 0000000000..7b21230fb6
--- /dev/null
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java
@@ -0,0 +1,284 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.apache.commons.lang3.SystemUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
+
+public class IOUtilTest {
+
+ @Test
+ public void testReadAllBytes() throws IOException {
+ byte[] data = "12345".getBytes(StandardCharsets.UTF_8);
+ try (InputStream stream = new ByteArrayInputStream(data)) {
+ byte[] bytes = IOUtil.toByteArray(stream);
+ Assert.assertEquals(5, bytes.length);
+ Assert.assertArrayEquals(data, bytes);
+ }
+ }
+
+ @Test
+ public void testToByteArrayResize() throws IOException {
+ int size = 8192 + 8192 + 10;
+ byte[] data = new byte[size];
+ for (int i = 0; i < size; i++) {
+ data[i] = 'A';
+ }
+ try (InputStream stream = new ByteArrayInputStream(data)) {
+ byte[] bytes = IOUtil.toByteArray(stream);
+ Assert.assertEquals(size, bytes.length);
+ Assert.assertArrayEquals(data, bytes);
+ }
+ }
+
+ @Test
+ public void testSkipFully() throws IOException {
+ byte[] data = "12345".getBytes(StandardCharsets.UTF_8);
+ try (InputStream stream = new ByteArrayInputStream(data)) {
+ Assert.assertThrows(IllegalArgumentException.class, new ThrowingRunnable() {
+ @Override
+ public void run() throws Throwable {
+ IOUtil.skipFully(stream, -1);
+ }
+ });
+
+ Assert.assertEquals(3, IOUtil.skipFully(stream, 3));
+ byte[] bytes = IOUtil.toByteArray(stream);
+ Assert.assertEquals(2, bytes.length);
+ Assert.assertArrayEquals("45".getBytes(StandardCharsets.UTF_8), bytes);
+ }
+ }
+
+ @Test
+ public void testSkipFully2() throws IOException {
+ byte[] data = "12345".getBytes(StandardCharsets.UTF_8);
+ try (InputStream stream = new ByteArrayInputStream(data)) {
+ // skip more bytes than the stream contains
+ Assert.assertEquals(data.length, IOUtil.skipFully(stream, data.length + 1));
+ byte[] bytes = IOUtil.toByteArray(stream);
+ Assert.assertEquals(0, bytes.length);
+ }
+ }
+
+ @Test
+ public void testNormalizePath() {
+ if (SystemUtils.IS_OS_UNIX) {
+ Assert.assertEquals("ab/cd.txt", IOUtil.normalizePath("ab/ef/../cd.txt"));
+ Assert.assertEquals("/a.txt", IOUtil.normalizePath("/x/../../a.txt"));
+ Assert.assertEquals("/foo", IOUtil.normalizePath("//../foo"));
+ Assert.assertEquals("/foo", IOUtil.normalizePath("/foo//"));
+ Assert.assertEquals("/foo", IOUtil.normalizePath("/foo/./"));
+ Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar"));
+ Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar/"));
+ Assert.assertEquals("/baz", IOUtil.normalizePath("/foo/../bar/../baz"));
+ Assert.assertEquals("/foo/bar", IOUtil.normalizePath("//foo//./bar"));
+ Assert.assertEquals("foo", IOUtil.normalizePath("foo/bar/.."));
+ Assert.assertEquals("bar", IOUtil.normalizePath("foo/../bar"));
+ Assert.assertEquals("/foo/baz", IOUtil.normalizePath("//foo/bar/../baz"));
+ Assert.assertEquals("~/bar", IOUtil.normalizePath("~/foo/../bar/"));
+ Assert.assertEquals("/", IOUtil.normalizePath("/../"));
+ Assert.assertEquals("bar", IOUtil.normalizePath("~/../bar"));
+ Assert.assertEquals("bar", IOUtil.normalizePath("./bar"));
+
+ Assert.assertNull(IOUtil.normalizePath("../foo"));
+ Assert.assertNull(IOUtil.normalizePath("foo/../../bar"));
+ Assert.assertNull(IOUtil.normalizePath("."));
+
+ Assert.assertTrue(IOUtil.equalsNormalizedPaths("foo/../bar", "bar/./"));
+ }
+
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Assert.assertEquals("ab\\cd.txt", IOUtil.normalizePath("ab\\ef\\..\\cd.txt"));
+ Assert.assertEquals("\\a.txt", IOUtil.normalizePath("\\x\\..\\..\\a.txt"));
+ Assert.assertEquals("\\foo", IOUtil.normalizePath("\\foo\\\\"));
+ Assert.assertEquals("\\foo", IOUtil.normalizePath("\\foo\\.\\"));
+ Assert.assertEquals("\\bar", IOUtil.normalizePath("\\foo\\..\\bar"));
+ Assert.assertEquals("\\bar", IOUtil.normalizePath("\\foo\\..\\bar\\"));
+ Assert.assertEquals("\\baz", IOUtil.normalizePath("\\foo\\..\\bar\\..\\baz"));
+ Assert.assertEquals("\\\\foo\\bar\\", IOUtil.normalizePath("\\\\foo\\bar"));
+ Assert.assertEquals("\\\\foo\\bar\\baz", IOUtil.normalizePath("\\\\foo\\bar\\..\\baz"));
+ Assert.assertEquals("foo", IOUtil.normalizePath("foo\\bar\\.."));
+ Assert.assertEquals("bar", IOUtil.normalizePath("foo\\..\\bar"));
+ Assert.assertEquals("\\foo\\baz", IOUtil.normalizePath("\\foo\\bar\\..\\baz"));
+ Assert.assertEquals("\\", IOUtil.normalizePath("\\..\\"));
+ Assert.assertEquals("bar", IOUtil.normalizePath(".\\bar"));
+
+ Assert.assertNull(IOUtil.normalizePath("\\\\..\\foo"));
+ Assert.assertNull(IOUtil.normalizePath("..\\foo"));
+ Assert.assertNull(IOUtil.normalizePath("foo\\..\\..\\bar"));
+ Assert.assertNull(IOUtil.normalizePath("."));
+ Assert.assertNull(IOUtil.normalizePath("\\\\foo\\\\.\\bar"));
+ Assert.assertNull(IOUtil.normalizePath("\\\\foo\\.\\bar"));
+
+ Assert.assertTrue(IOUtil.equalsNormalizedPaths("foo\\..\\bar", "bar\\.\\"));
+
+ Assert.assertEquals("C:\\bar", IOUtil.normalizePath("C:\\..\\bar"));
+ Assert.assertEquals("ab\\cd.txt", IOUtil.normalizePath("ab\\ef\\..\\cd.txt"));
+ Assert.assertEquals("C:\\ab\\cd.txt", IOUtil.normalizePath("C:\\ab\\ef\\..\\.\\cd.txt"));
+ Assert.assertNull(IOUtil.normalizePath("..\\foo"));
+ Assert.assertNull(IOUtil.normalizePath("foo\\..\\..\\bar"));
+ }
+ }
+
+ @Test
+ public void testFilenameExtension() {
+ Assert.assertEquals("txt", IOUtil.getFilenameExtension("ab/cd.txt"));
+ Assert.assertEquals("txt", IOUtil.getFilenameExtension("ab.cd.txt"));
+ Assert.assertEquals("", IOUtil.getFilenameExtension("ab/cd"));
+ Assert.assertEquals("html", IOUtil.getFilenameExtension("cd.html"));
+ }
+
+ @Test
+ public void testFilenameBase() {
+ Assert.assertEquals("cd", IOUtil.getFilenameBase("ab/cd.txt"));
+ Assert.assertEquals("ab.cd", IOUtil.getFilenameBase("ab.cd.txt"));
+ Assert.assertEquals("cd", IOUtil.getFilenameBase("ab/cd"));
+ }
+
+ @Test
+ public void testBomAwareStream() throws IOException {
+ assertBomStream("No BOM".getBytes(StandardCharsets.UTF_8), "No BOM", null);
+ assertBomStream("\ufeffBOM".getBytes(StandardCharsets.UTF_8), "BOM", StandardCharsets.UTF_8.name());
+ assertBomStream("\ufeffBOM".getBytes(StandardCharsets.UTF_16LE), "BOM", StandardCharsets.UTF_16LE.name());
+ assertBomStream("\ufeffBOM".getBytes(StandardCharsets.UTF_16BE), "BOM", StandardCharsets.UTF_16BE.name());
+ }
+
+ private void assertBomStream(byte[] data, String expectedData, String expectedCharset) throws IOException {
+ try (IOUtil.BomAwareInputStream stream = new IOUtil.BomAwareInputStream(new ByteArrayInputStream(data))) {
+ if (expectedCharset != null) {
+ Assert.assertTrue(stream.hasBom());
+ Assert.assertEquals(expectedCharset, stream.getBomCharsetName());
+ Assert.assertEquals(expectedData, new String(IOUtil.toByteArray(stream), stream.getBomCharsetName()));
+
+ } else {
+ Assert.assertFalse(stream.hasBom());
+ Assert.assertNull(stream.getBomCharsetName());
+ Assert.assertEquals(expectedData, new String(IOUtil.toByteArray(stream), StandardCharsets.UTF_8));
+ }
+ }
+ }
+
+ @Test
+ public void testOutputStreamFromWriter() throws IOException {
+ StringWriter writer = new StringWriter();
+ try (OutputStream outputStream = IOUtil.fromWriter(writer, "UTF-8")) {
+ outputStream.write("abc".getBytes(StandardCharsets.UTF_8));
+ }
+ Assert.assertEquals("abc", writer.toString());
+ }
+
+ @Test
+ public void testInputStreamFromReader() throws IOException {
+ try (InputStream inputStream = IOUtil.fromReader(new StringReader("abc"))) {
+ byte[] bytes = IOUtil.toByteArray(inputStream);
+ Assert.assertEquals("abc", new String(bytes, StandardCharsets.UTF_8));
+ }
+ }
+
+ @Test
+ public void testCopyStream() throws IOException {
+ int size = 8192 + 8192 + 10;
+ byte[] data = new byte[size];
+ for (int i = 0; i < size; i++) {
+ data[i] = 'A';
+ }
+ try (InputStream stream = new ByteArrayInputStream(data);
+ ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ IOUtil.copy(stream, out);
+ byte[] bytes = out.toByteArray();
+ Assert.assertEquals(size, bytes.length);
+ Assert.assertArrayEquals(data, bytes);
+ }
+ }
+
+ @Test
+ public void testCopyReader() throws IOException {
+ int size = 8192 + 8192 + 10;
+ char[] data = new char[size];
+ for (int i = 0; i < size; i++) {
+ data[i] = 'A';
+ }
+ try (Reader reader = new CharArrayReader(data);
+ StringWriter writer = new StringWriter()) {
+ IOUtil.copy(reader, writer);
+ char[] chars = writer.toString().toCharArray();
+ Assert.assertEquals(size, chars.length);
+ Assert.assertArrayEquals(data, chars);
+ }
+ }
+
+ @Test
+ public void testReadEmptyStream() throws IOException {
+ try (InputStream in = new ByteArrayInputStream(new byte[0])) {
+ byte[] bytes = IOUtil.toByteArray(in);
+ Assert.assertNotNull(bytes);
+ Assert.assertEquals(0, bytes.length);
+ }
+ }
+
+ @Test
+ public void testCloseQuietly() {
+ class Stream extends InputStream {
+ private boolean closed = false;
+
+ @Override
+ public int read() throws IOException {
+ return 0;
+ }
+
+ @Override
+ public void close() throws IOException {
+ closed = true;
+ throw new IOException("test");
+ }
+
+ public boolean isClosed() {
+ return closed;
+ }
+ }
+
+ Stream stream = new Stream();
+ IOUtil.closeQuietly(stream);
+ Assert.assertTrue(stream.isClosed());
+ }
+
+ @Test
+ public void testReadFileToString() throws IOException {
+ String testString = "Test ABC";
+ Path tempFile = Files.createTempFile("pmd", ".txt");
+ Files.write(tempFile, testString.getBytes(Charset.defaultCharset()));
+ Assert.assertEquals(testString, IOUtil.readFileToString(tempFile.toFile()));
+ }
+
+ @Test
+ public void testReadToString() throws IOException {
+ String testString = "testReadToString";
+ Reader reader = new StringReader(testString);
+ Assert.assertEquals(testString, IOUtil.readToString(reader));
+ }
+
+ @Test
+ public void testReadStreamToString() throws IOException {
+ String testString = "testReadStreamToString";
+ InputStream stream = new ByteArrayInputStream(testString.getBytes(StandardCharsets.UTF_8));
+ Assert.assertEquals(testString, IOUtil.readToString(stream, StandardCharsets.UTF_8));
+ }
+}
diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java
index 2282641b40..7b3aa6e48e 100644
--- a/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java
+++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java
@@ -7,6 +7,7 @@ package net.sourceforge.pmd.util.treeexport;
import static org.hamcrest.Matchers.containsString;
import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -15,7 +16,6 @@ import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
-import org.apache.commons.io.IOUtils;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.junit.Assert;
@@ -67,7 +67,7 @@ public class TreeExportCliTest {
}
private static InputStream stdinContaining(String input) {
- return IOUtils.toInputStream(input, StandardCharsets.UTF_8);
+ return new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));
}
static class IoSpy {
diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml
index e8d3b680af..ec704c797e 100644
--- a/pmd-dist/pom.xml
+++ b/pmd-dist/pom.xml
@@ -271,10 +271,6 @@
slf4j-simple