Tests for readonlyness
This commit is contained in:
4 files changed
+139
-46
No files matched your search
@@ -48,6 +48,7 @@ import net.sourceforge.pmd.util.log.MessageReporter;
|
||||
*/
|
||||
@SuppressWarnings("PMD.CloseResource")
|
||||
public final class FileCollector implements AutoCloseable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileCollector.class);
|
||||
|
||||
private final List<TextFile> allFilesToProcess = new ArrayList<>();
|
||||
@@ -167,8 +168,11 @@ public final class FileCollector implements AutoCloseable {
|
||||
reporter.error("Not a regular file {}", file);
|
||||
return false;
|
||||
}
|
||||
NioTextFile nioTextFile = new NioTextFile(file, charset, discoverer.getDefaultLanguageVersion(language), getDisplayName(file));
|
||||
addFileImpl(nioTextFile);
|
||||
LanguageVersion lv = discoverer.getDefaultLanguageVersion(language);
|
||||
Objects.requireNonNull(lv);
|
||||
addFileImpl(TextFile.builderForPath(file, charset, lv)
|
||||
.withDisplayName(getDisplayName(file))
|
||||
.build());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -371,7 +375,7 @@ public final class FileCollector implements AutoCloseable {
|
||||
*/
|
||||
public void exclude(FileCollector excludeCollector) {
|
||||
Set<TextFile> toExclude = new HashSet<>(excludeCollector.allFilesToProcess);
|
||||
for (Iterator<TextFile> iterator = allFilesToProcess.iterator(); iterator.hasNext();) {
|
||||
for (Iterator<TextFile> iterator = allFilesToProcess.iterator(); iterator.hasNext(); ) {
|
||||
TextFile file = iterator.next();
|
||||
if (toExclude.contains(file)) {
|
||||
LOG.trace("Excluding file {}", file.getPathId());
|
||||
@@ -385,7 +389,7 @@ public final class FileCollector implements AutoCloseable {
|
||||
* collection.
|
||||
*/
|
||||
public void filterLanguages(Set<Language> languages) {
|
||||
for (Iterator<TextFile> iterator = allFilesToProcess.iterator(); iterator.hasNext();) {
|
||||
for (Iterator<TextFile> iterator = allFilesToProcess.iterator(); iterator.hasNext(); ) {
|
||||
TextFile file = iterator.next();
|
||||
Language lang = file.getLanguageVersion().getLanguage();
|
||||
if (!languages.contains(lang)) {
|
||||
|
||||
@@ -27,13 +27,19 @@ class NioTextFile extends BaseCloseable implements TextFile {
|
||||
private final Charset charset;
|
||||
private final LanguageVersion languageVersion;
|
||||
private final @Nullable String displayName;
|
||||
private boolean readOnly;
|
||||
|
||||
NioTextFile(Path path, Charset charset, LanguageVersion languageVersion, @Nullable String displayName) {
|
||||
NioTextFile(Path path,
|
||||
Charset charset,
|
||||
LanguageVersion languageVersion,
|
||||
@Nullable String displayName,
|
||||
boolean readOnly) {
|
||||
AssertionUtil.requireParamNotNull("path", path);
|
||||
AssertionUtil.requireParamNotNull("charset", charset);
|
||||
AssertionUtil.requireParamNotNull("language version", languageVersion);
|
||||
|
||||
this.displayName = displayName;
|
||||
this.readOnly = readOnly;
|
||||
this.path = path;
|
||||
this.charset = charset;
|
||||
this.languageVersion = languageVersion;
|
||||
@@ -56,12 +62,15 @@ class NioTextFile extends BaseCloseable implements TextFile {
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return !Files.isWritable(path);
|
||||
return readOnly || !Files.isWritable(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeContents(TextFileContent content) throws IOException {
|
||||
ensureOpen();
|
||||
if (isReadOnly()) {
|
||||
throw new ReadOnlyFileException();
|
||||
}
|
||||
try (BufferedWriter bw = Files.newBufferedWriter(path, charset)) {
|
||||
if (content.getLineTerminator().equals(TextFileContent.NORMALIZED_LINE_TERM)) {
|
||||
content.getNormalizedText().writeFully(bw);
|
||||
|
||||
@@ -26,10 +26,41 @@ public abstract class TextFileBuilder {
|
||||
this.languageVersion = AssertionUtil.requireParamNotNull("language version", languageVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the built file is read only. Some text files are
|
||||
* always read-only.
|
||||
*
|
||||
* @return This builder
|
||||
*/
|
||||
public TextFileBuilder asReadOnly() {
|
||||
// default is appropriate if the file type is always read-only
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a custom display name for the new file. If null, or this is
|
||||
* never called, the display name defaults to the path ID.
|
||||
*
|
||||
* @param displayName A display name
|
||||
*
|
||||
* @return This builder
|
||||
*/
|
||||
public TextFileBuilder withDisplayName(@Nullable String displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the new text file.
|
||||
*/
|
||||
public abstract TextFile build();
|
||||
|
||||
static class ForNio extends TextFileBuilder {
|
||||
|
||||
private final Path path;
|
||||
private final Charset charset;
|
||||
private boolean readOnly = false;
|
||||
|
||||
ForNio(LanguageVersion languageVersion, Path path, Charset charset) {
|
||||
super(languageVersion);
|
||||
@@ -37,9 +68,15 @@ public abstract class TextFileBuilder {
|
||||
this.charset = AssertionUtil.requireParamNotNull("charset", charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextFileBuilder asReadOnly() {
|
||||
readOnly = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextFile build() {
|
||||
return new NioTextFile(path, charset, languageVersion, displayName);
|
||||
return new NioTextFile(path, charset, languageVersion, displayName, readOnly);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,22 +114,4 @@ public abstract class TextFileBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a custom display name for the new file. If null, or this is
|
||||
* never called, the display name defaults to the path ID.
|
||||
*
|
||||
* @param displayName A display name
|
||||
*
|
||||
* @return This builder
|
||||
*/
|
||||
public TextFileBuilder withDisplayName(@Nullable String displayName) {
|
||||
this.displayName = displayName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the new text file.
|
||||
*/
|
||||
public abstract TextFile build();
|
||||
}
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.document;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -13,7 +18,6 @@ import java.nio.file.Path;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
@@ -32,10 +36,47 @@ public class TextFilesTest {
|
||||
public void testNioFile() throws IOException {
|
||||
Path file = makeTmpFile(StandardCharsets.UTF_8, "some content");
|
||||
try (TextFile tf = TextFile.forPath(file, StandardCharsets.UTF_8, dummyVersion)) {
|
||||
Assert.assertEquals(file.toAbsolutePath().toString(), tf.getPathId());
|
||||
Assert.assertEquals(file.toString(), tf.getDisplayName());
|
||||
Assert.assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
Assert.assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
assertEquals(file.toAbsolutePath().toString(), tf.getPathId());
|
||||
assertEquals(file.toString(), tf.getDisplayName());
|
||||
assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNioFileWrite() throws IOException {
|
||||
Path file = makeTmpFile(StandardCharsets.UTF_8, "some content");
|
||||
try (TextFile tf = TextFile.forPath(file, StandardCharsets.UTF_8, dummyVersion)) {
|
||||
assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
assertFalse("readonly", tf.isReadOnly());
|
||||
|
||||
tf.writeContents(
|
||||
TextFileContent.fromCharSeq("new content")
|
||||
);
|
||||
|
||||
assertEquals(Chars.wrap("new content"), tf.readContents().getNormalizedText());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNioFileExplicitReadOnly() throws IOException {
|
||||
Path file = makeTmpFile(StandardCharsets.UTF_8, "some content");
|
||||
try (TextFile tf = TextFile.builderForPath(file, StandardCharsets.UTF_8, dummyVersion)
|
||||
.asReadOnly().build()) {
|
||||
assertTrue("readonly", tf.isReadOnly());
|
||||
|
||||
assertThrows(ReadOnlyFileException.class, () -> tf.writeContents(
|
||||
TextFileContent.fromCharSeq("new content")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNioFileCanBeReadMultipleTimes() throws IOException {
|
||||
Path file = makeTmpFile(StandardCharsets.UTF_8, "some content");
|
||||
try (TextFile tf = TextFile.forPath(file, StandardCharsets.UTF_8, dummyVersion)) {
|
||||
assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +86,10 @@ public class TextFilesTest {
|
||||
try (TextFile tf = TextFile.builderForPath(file, StandardCharsets.UTF_8, dummyVersion)
|
||||
.withDisplayName("aname")
|
||||
.build()) {
|
||||
Assert.assertEquals(file.toAbsolutePath().toString(), tf.getPathId());
|
||||
Assert.assertEquals("aname", tf.getDisplayName());
|
||||
Assert.assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
Assert.assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
assertEquals(file.toAbsolutePath().toString(), tf.getPathId());
|
||||
assertEquals("aname", tf.getDisplayName());
|
||||
assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +97,7 @@ public class TextFilesTest {
|
||||
public void testNioFileEscape() throws IOException {
|
||||
Path file = makeTmpFile(StandardCharsets.UTF_8, "some\r\ncontent");
|
||||
try (TextFile tf = TextFile.forPath(file, StandardCharsets.UTF_8, dummyVersion)) {
|
||||
Assert.assertEquals(Chars.wrap("some\ncontent"), tf.readContents().getNormalizedText());
|
||||
assertEquals(Chars.wrap("some\ncontent"), tf.readContents().getNormalizedText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,22 +105,42 @@ public class TextFilesTest {
|
||||
public void testReaderFileEscape() throws IOException {
|
||||
Path file = makeTmpFile(StandardCharsets.UTF_8, "some\r\ncontent");
|
||||
try (TextFile tf = TextFile.forReader(Files.newBufferedReader(file, StandardCharsets.UTF_8), "filename", dummyVersion)) {
|
||||
Assert.assertEquals("filename", tf.getPathId());
|
||||
Assert.assertEquals("filename", tf.getDisplayName());
|
||||
Assert.assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
Assert.assertEquals(Chars.wrap("some\ncontent"), tf.readContents().getNormalizedText());
|
||||
Assert.assertThrows(ReadOnlyFileException.class, () -> tf.writeContents(
|
||||
assertEquals("filename", tf.getPathId());
|
||||
assertEquals("filename", tf.getDisplayName());
|
||||
assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
assertEquals(Chars.wrap("some\ncontent"), tf.readContents().getNormalizedText());
|
||||
assertThrows(ReadOnlyFileException.class, () -> tf.writeContents(
|
||||
TextFileContent.fromCharSeq("new content")
|
||||
));
|
||||
}
|
||||
}@Test
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringFileEscape() throws IOException {
|
||||
try (TextFile tf = TextFile.forCharSeq("cont\r\nents", "filename", dummyVersion)) {
|
||||
Assert.assertEquals("filename", tf.getPathId());
|
||||
Assert.assertEquals("filename", tf.getDisplayName());
|
||||
Assert.assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
Assert.assertEquals(Chars.wrap("cont\r\nent"), tf.readContents().getNormalizedText());
|
||||
Assert.assertThrows(ReadOnlyFileException.class, () -> tf.writeContents(
|
||||
assertEquals("filename", tf.getPathId());
|
||||
assertEquals("filename", tf.getDisplayName());
|
||||
assertEquals(dummyVersion, tf.getLanguageVersion());
|
||||
assertEquals(Chars.wrap("cont\nents"), tf.readContents().getNormalizedText());
|
||||
assertThrows(ReadOnlyFileException.class, () -> tf.writeContents(
|
||||
TextFileContent.fromCharSeq("new content")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringFileCanBeReadMultipleTimes() throws IOException {
|
||||
try (TextFile tf = TextFile.forCharSeq("contents", "filename", dummyVersion)) {
|
||||
assertEquals(Chars.wrap("contents"), tf.readContents().getNormalizedText());
|
||||
assertEquals(Chars.wrap("contents"), tf.readContents().getNormalizedText());
|
||||
assertEquals(Chars.wrap("contents"), tf.readContents().getNormalizedText());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringFileIsReadonly() throws IOException {
|
||||
try (TextFile tf = TextFile.forCharSeq("contents", "filename", dummyVersion)) {
|
||||
assertThrows(ReadOnlyFileException.class, () -> tf.writeContents(
|
||||
TextFileContent.fromCharSeq("new content")
|
||||
));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user