diff --git a/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/JavaFiles.java b/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/JavaFiles.java index f3e471e8615..90abd21453b 100644 --- a/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/JavaFiles.java +++ b/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/JavaFiles.java @@ -23,6 +23,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collections; import java.util.List; @State(Scope.Benchmark) @@ -38,10 +39,13 @@ public void setup() throws URISyntaxException, IOException { throw new RuntimeException("Unable to create directory"); } - sourceFiles = new ArrayList<>(1_000); - for (int i = 0; i < 1_000; i++) { - Files.writeString(test.resolve("Test" + i + ".java"), - "package test; class Test" + i + " {}"); + sourceFiles = new ArrayList<>(100); + // to add some "meat to the bones" + String whitespace = String.join("", Collections.nCopies(1_000, " ")); + for (int i = 0; i < 100; i++) { + Path path = test.resolve("Test" + i + ".java"); + Files.writeString(path, "package test; class Test%d {%s}".formatted(i, whitespace)); + sourceFiles.add(path); } } diff --git a/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/ParserInputBenchmark.java b/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/ParserInputBenchmark.java index d74728c6923..ab16e62bf78 100644 --- a/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/ParserInputBenchmark.java +++ b/rewrite-benchmarks/src/jmh/java/org/openrewrite/benchmarks/java/ParserInputBenchmark.java @@ -16,6 +16,7 @@ package org.openrewrite.benchmarks.java; import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; @@ -23,11 +24,9 @@ import org.openrewrite.InMemoryExecutionContext; import org.openrewrite.Parser; import org.openrewrite.java.JavaParser; +import org.openrewrite.tree.ParsingExecutionContextView; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; +import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; import static java.util.stream.Collectors.toList; @@ -35,45 +34,35 @@ @Fork(1) @Measurement(iterations = 2) @Warmup(iterations = 2) -@BenchmarkMode(Mode.SampleTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) @Threads(4) public class ParserInputBenchmark { @Benchmark - public void readFromDisk(JavaFiles state) { - //language=java + public void detectCharset(JavaFiles state, Blackhole bh) { JavaParser.fromJavaVersion().build() .parseInputs(state.getSourceFiles().stream() - .map(sourceFile -> new Parser.Input(sourceFile, () -> { - try { - return Files.newInputStream(sourceFile); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }) - ) + .map(Parser.Input::fromFile) .collect(toList()), null, - new InMemoryExecutionContext()); + new InMemoryExecutionContext() + ) + .forEach(bh::consume); } @Benchmark - public void readFromDiskWithBufferedInputStream(JavaFiles state) { - //language=java + public void knownCharset(JavaFiles state, Blackhole bh) { + ParsingExecutionContextView ctx = ParsingExecutionContextView.view(new InMemoryExecutionContext()) + .setCharset(StandardCharsets.UTF_8); JavaParser.fromJavaVersion().build() .parseInputs(state.getSourceFiles().stream() - .map(sourceFile -> new Parser.Input(sourceFile, () -> { - try { - return new BufferedInputStream(Files.newInputStream(sourceFile)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }) - ) + .map(Parser.Input::fromFile) .collect(toList()), null, - new InMemoryExecutionContext()); + ctx + ) + .forEach(bh::consume); } public static void main(String[] args) throws RunnerException { diff --git a/rewrite-core/src/main/java/org/openrewrite/Parser.java b/rewrite-core/src/main/java/org/openrewrite/Parser.java index fd308a2d86d..2b38025ff18 100644 --- a/rewrite-core/src/main/java/org/openrewrite/Parser.java +++ b/rewrite-core/src/main/java/org/openrewrite/Parser.java @@ -177,6 +177,16 @@ public static Input fromString(Path sourcePath, String source, Charset charset) return new Input(sourcePath, null, () -> new ByteArrayInputStream(source.getBytes(charset)), true); } + public static Input fromFile(Path sourcePath) { + return new Input(sourcePath, FileAttributes.fromPath(sourcePath), () -> { + try { + return Files.newInputStream(sourcePath); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }, false); + } + @SuppressWarnings("unused") public static Input fromResource(String resource) { return new Input( diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/EncodingDetectingInputStream.java b/rewrite-core/src/main/java/org/openrewrite/internal/EncodingDetectingInputStream.java index 1dae79b4763..648b5817952 100644 --- a/rewrite-core/src/main/java/org/openrewrite/internal/EncodingDetectingInputStream.java +++ b/rewrite-core/src/main/java/org/openrewrite/internal/EncodingDetectingInputStream.java @@ -20,17 +20,20 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class EncodingDetectingInputStream extends InputStream { private static final Charset WINDOWS_1252 = Charset.forName("Windows-1252"); + private static final byte[] UTF8_BOM = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}; private final InputStream inputStream; @Nullable private Charset charset; + private boolean bomChecked; private boolean charsetBomMarked; /** @@ -38,15 +41,13 @@ public class EncodingDetectingInputStream extends InputStream { */ private int prev; private int prev2; - private int prev3; boolean maybeTwoByteSequence = false; boolean maybeThreeByteSequence = false; boolean maybeFourByteSequence = false; public EncodingDetectingInputStream(InputStream inputStream) { - this.inputStream = inputStream; - this.charset = null; + this(inputStream, null); } public EncodingDetectingInputStream(InputStream inputStream, @Nullable Charset charset) { @@ -64,71 +65,92 @@ public boolean isCharsetBomMarked() { @Override public int read() throws IOException { - int aByte = inputStream.read(); + int read; + if (!bomChecked) { + if (charset == null || charset == StandardCharsets.UTF_8) { + read = checkAndSkipUtf8Bom(); + if (charsetBomMarked) { + read = inputStream.read(); + } + } else { + bomChecked = true; + read = inputStream.read(); + } + } else { + read = inputStream.read(); + } + // if we haven't yet determined a charset... + if (read == -1) { + if (charset == null) { + if (maybeTwoByteSequence || maybeThreeByteSequence || maybeFourByteSequence) { + charset = WINDOWS_1252; + } else { + charset = StandardCharsets.UTF_8; + } + } + } else if (charset == null) { + guessCharset(read); + } + return read; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { if (charset == null) { - guessCharset(aByte); + // we need to read the bytes one-by-one to determine the encoding + return super.read(b, off, len); + } else if (charset == StandardCharsets.UTF_8 && !bomChecked) { + int read = checkAndSkipUtf8Bom(); + if (read == -1) { + return -1; + } else if (!charsetBomMarked) { + b[off++] = (byte) read; + } + read = inputStream.read(b, off, len - 1); + return read == -1 ? charsetBomMarked ? -1 : 1 : (charsetBomMarked ? 0 : 1) + read; + } else { + return inputStream.read(b, off, len); } - return aByte; } private void guessCharset(int aByte) { - if (prev3 == 0xEF && prev2 == 0xBB && prev == 0xBF) { - charsetBomMarked = true; - charset = StandardCharsets.UTF_8; - } else { - if (aByte == -1 || !(prev2 == 0 && prev == 0xEF || prev3 == 0 && prev2 == 0xEF)) { - if (maybeTwoByteSequence) { - if (aByte == -1 && !utf8SequenceEnd(prev) || aByte != -1 && !(utf8SequenceEnd(aByte))) { - charset = WINDOWS_1252; - } else { - maybeTwoByteSequence = false; - prev2 = -1; - prev = -1; - } - } else if (maybeThreeByteSequence) { - if (aByte == -1 || - utf8SequenceEnd(prev) && !(utf8SequenceEnd(aByte)) || - !utf8SequenceEnd(aByte)) { - charset = WINDOWS_1252; - } - - if (utf8SequenceEnd(prev) && utf8SequenceEnd(aByte)) { - maybeThreeByteSequence = false; - prev2 = -1; - prev = -1; - } - } else if (maybeFourByteSequence) { - if (aByte == -1 || - utf8SequenceEnd(prev2) && utf8SequenceEnd(prev) && !utf8SequenceEnd(aByte) || - utf8SequenceEnd(prev) && !utf8SequenceEnd(aByte) || - !(utf8SequenceEnd(aByte))) { - charset = WINDOWS_1252; - } - - if (utf8SequenceEnd(prev2) && utf8SequenceEnd(prev) && utf8SequenceEnd(aByte)) { - maybeFourByteSequence = false; - prev2 = -1; - prev = -1; - } - } else if (utf8TwoByteSequence(aByte)) { - maybeTwoByteSequence = true; - } else if (utf8ThreeByteSequence(aByte)) { - maybeThreeByteSequence = true; - } else if (utf8FourByteSequence(aByte)) { - maybeFourByteSequence = true; - } else if (!utf8TwoByteSequence(prev) && utf8SequenceEnd(aByte)) { - charset = WINDOWS_1252; - } + if (utf8TwoByteSequence(aByte)) { + maybeTwoByteSequence = true; + } else if (utf8ThreeByteSequence(aByte)) { + maybeThreeByteSequence = true; + } else if (utf8FourByteSequence(aByte)) { + maybeFourByteSequence = true; + } else if (maybeTwoByteSequence) { + if (!utf8SequenceEnd(aByte)) { + charset = WINDOWS_1252; + } else { + maybeTwoByteSequence = false; + prev = -1; + } + } else if (maybeThreeByteSequence) { + if (!utf8SequenceEnd(aByte)) { + charset = WINDOWS_1252; } - if (aByte == -1 && charset == null) { - charset = StandardCharsets.UTF_8; + if (utf8SequenceEnd(prev) && utf8SequenceEnd(aByte)) { + maybeThreeByteSequence = false; + prev = -1; + } + } else if (maybeFourByteSequence) { + if (utf8SequenceEnd(prev2) && utf8SequenceEnd(prev) && !utf8SequenceEnd(aByte) || utf8SequenceEnd(prev) && !utf8SequenceEnd(aByte) || !utf8SequenceEnd(aByte)) { + charset = WINDOWS_1252; } + + if (utf8SequenceEnd(prev2) && utf8SequenceEnd(prev) && utf8SequenceEnd(aByte)) { + maybeFourByteSequence = false; + prev = -1; + } + } else if (utf8SequenceEnd(aByte)) { + charset = WINDOWS_1252; } - prev3 = prev2; prev2 = prev; prev = aByte; } @@ -143,14 +165,36 @@ public synchronized String toString() { }; byte[] buffer = new byte[4096]; int n; - while ((n = is.read(buffer)) != -1) { + // Note that `is` is this, so the BOM will be checked in `read()` + while ((n = is.read(buffer, 0, buffer.length)) != -1) { bos.write(buffer, 0, n); } return bos.toString(); } catch (IOException e) { - throw new UnsupportedOperationException(e); + throw new UncheckedIOException(e); + } + } + + private int checkAndSkipUtf8Bom() throws IOException { + // `Files#newInputStream()` does not need to support mark/reset, so one at the time... + bomChecked = true; + int read = inputStream.read(); + if ((byte) read != UTF8_BOM[0]) { + return read; + } + read = inputStream.read(); + if ((byte) read != UTF8_BOM[1]) { + return read; + } + read = inputStream.read(); + if ((byte) read != UTF8_BOM[2]) { + return read; } + charsetBomMarked = true; + charset = StandardCharsets.UTF_8; + // return anything other that -1 + return -2; } // The first byte of a UTF-8 two byte sequence is between 0xC0 - 0xDF. diff --git a/rewrite-core/src/test/java/org/openrewrite/ParserTest.java b/rewrite-core/src/test/java/org/openrewrite/ParserTest.java index 0f1b00fdb4e..ae3246361c5 100644 --- a/rewrite-core/src/test/java/org/openrewrite/ParserTest.java +++ b/rewrite-core/src/test/java/org/openrewrite/ParserTest.java @@ -21,7 +21,6 @@ import org.openrewrite.tree.ParseError; import org.openrewrite.tree.ParsingExecutionContextView; -import java.io.ByteArrayInputStream; import java.nio.file.Path; import java.nio.file.Paths; @@ -80,8 +79,8 @@ void printIdempotentDiffPrint() { line 2 """; - Parser.Input input1 = new Parser.Input(path, () -> new ByteArrayInputStream(before.getBytes())); - Parser.Input input2 = new Parser.Input(path, () -> new ByteArrayInputStream(after.getBytes())); + Parser.Input input1 = Parser.Input.fromString(path, before); + Parser.Input input2 = Parser.Input.fromString(path, after); SourceFile s1 = parser.parse(input1.getSource(ctx).readFully()).toList().get(0); SourceFile out = parser.requirePrintEqualsInput(s1, input2, null, ctx); assertThat(out).isInstanceOf(ParseError.class); diff --git a/rewrite-core/src/test/java/org/openrewrite/internal/EncodingDetectingInputStreamTest.java b/rewrite-core/src/test/java/org/openrewrite/internal/EncodingDetectingInputStreamTest.java index d17a64254c3..68205549167 100644 --- a/rewrite-core/src/test/java/org/openrewrite/internal/EncodingDetectingInputStreamTest.java +++ b/rewrite-core/src/test/java/org/openrewrite/internal/EncodingDetectingInputStreamTest.java @@ -33,8 +33,45 @@ class EncodingDetectingInputStreamTest { @Test void detectUTF8Bom() throws IOException { - String bom = "\uFEFF"; - try (EncodingDetectingInputStream is = read(bom, UTF_8)) { + String str = "\uFEFF"; + try (EncodingDetectingInputStream is = new EncodingDetectingInputStream(new ByteArrayInputStream(str.getBytes(UTF_8)))) { + assertThat(is.readFully()).isEqualTo(""); + assertThat(is.isCharsetBomMarked()).isTrue(); + } + } + + @Test + void emptyUtf8() throws IOException { + String str = ""; + try (EncodingDetectingInputStream is = new EncodingDetectingInputStream(new ByteArrayInputStream(str.getBytes(UTF_8)))) { + assertThat(is.readFully()).isEqualTo(str); + assertThat(is.isCharsetBomMarked()).isFalse(); + } + } + + @Test + void singleCharUtf8() throws IOException { + String str = "1"; + try (EncodingDetectingInputStream is = new EncodingDetectingInputStream(new ByteArrayInputStream(str.getBytes(UTF_8)))) { + assertThat(is.readFully()).isEqualTo(str); + assertThat(is.isCharsetBomMarked()).isFalse(); + } + } + + @Test + void skipUTF8Bom() throws IOException { + String bom = "\uFEFFhello"; + try (EncodingDetectingInputStream is = new EncodingDetectingInputStream(new ByteArrayInputStream(bom.getBytes(UTF_8)))) { + assertThat(is.readFully()).isEqualTo("hello"); + assertThat(is.isCharsetBomMarked()).isTrue(); + } + } + + @Test + void skipUTF8BomKnownEncoding() throws IOException { + String bom = "\uFEFFhello"; + try (EncodingDetectingInputStream is = new EncodingDetectingInputStream(new ByteArrayInputStream(bom.getBytes(UTF_8)), UTF_8)) { + assertThat(is.readFully()).isEqualTo("hello"); assertThat(is.isCharsetBomMarked()).isTrue(); } } diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java index 23534b40563..bbdf8337036 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java @@ -58,9 +58,9 @@ void shellScript() { groovy( """ #!/usr/bin/env groovy - + def a = 'hello' - """ + """ ) ); } diff --git a/rewrite-java/src/test/java/org/openrewrite/java/JavadocPrinterTest.java b/rewrite-java/src/test/java/org/openrewrite/java/JavadocPrinterTest.java index fd85de32ba4..3bc4b046c9f 100644 --- a/rewrite-java/src/test/java/org/openrewrite/java/JavadocPrinterTest.java +++ b/rewrite-java/src/test/java/org/openrewrite/java/JavadocPrinterTest.java @@ -58,4 +58,4 @@ class Test { ) ); } -} \ No newline at end of file +} diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java index e2a30d2263f..fde6936e423 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java @@ -32,7 +32,6 @@ import org.openrewrite.test.RewriteTest; import org.openrewrite.tree.ParseError; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.file.Paths; import java.util.Base64; @@ -938,8 +937,7 @@ public MockResponse dispatch(RecordedRequest request) { var ctx = MavenExecutionContextView.view(new InMemoryExecutionContext(t -> { throw new RuntimeException(t); })); - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> - new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ @@ -959,8 +957,8 @@ public MockResponse dispatch(RecordedRequest request) { - """.formatted(mockRepo.getHostName(), mockRepo.getPort(), username, password).getBytes() - )), ctx); + """.formatted(mockRepo.getHostName(), mockRepo.getPort(), username, password) + ), ctx); ctx.setMavenSettings(settings); var maven = MavenParser.builder().build().parse( diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/MavenSettingsTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/MavenSettingsTest.java index 8791dcaba93..8acbd05f729 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/MavenSettingsTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/MavenSettingsTest.java @@ -34,7 +34,6 @@ import org.openrewrite.xml.XmlParser; import org.openrewrite.xml.tree.Xml; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.Field; @@ -54,7 +53,7 @@ class MavenSettingsTest { @Test void parse() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getRepositories()).hasSize(1); } @@ -87,7 +86,7 @@ void parse() { @Issue("https://github.com/openrewrite/rewrite/issues/131") @Test void defaultActiveWhenNoOthersAreActive() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getRepositories().stream().map(MavenRepository::getUri)).containsExactly("https://activebydefault.com"); } @Test void idCollisionLastRepositoryWins() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getRepositories()) .as("When multiple repositories have the same id in a maven settings file the last one wins. In a pom.xml an error would be thrown.") @@ -169,7 +168,7 @@ void idCollisionLastRepositoryWins() { @Issue("https://github.com/openrewrite/rewrite/issues/131") @Test void defaultOnlyActiveIfNoOthersAreActive() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getActiveProfiles()) .containsExactly("repo"); @@ -219,7 +218,7 @@ void defaultOnlyActiveIfNoOthersAreActive() { @Issue("https://github.com/openrewrite/rewrite/issues/130") @Test void mirrorReplacesRepository() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getRepositories().stream() .map(repo -> MavenRepositoryMirror.apply(ctx.getMirrors(), repo)) @@ -261,7 +260,7 @@ void mirrorReplacesRepository() { @Test void starredMirrorWithExclusion() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getRepositories().stream() .map(repo -> MavenRepositoryMirror.apply(ctx.getMirrors(), repo))) @@ -316,7 +315,7 @@ void starredMirrorWithExclusion() { @Test void serverCredentials() { - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); assertThat(settings.getServers()).isNotNull(); assertThat(settings.getServers().getServers()).hasSize(1); @@ -345,7 +344,7 @@ void serverCredentials() { void serverTimeouts() { // Deliberately supporting the simpler old configuration of a single timeout // https://maven.apache.org/guides/mini/guide-http-settings.html#connection-timeouts - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); assertThat(settings.getServers()).isNotNull(); assertThat(settings.getServers().getServers()).hasSize(1); @@ -375,7 +374,7 @@ void serverTimeouts() { class LocalRepositoryTest { @Test void parsesLocalRepositoryPathFromSettingsXml(@TempDir Path localRepoPath) { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ %s - """.formatted(localRepoPath).getBytes() - )), ctx)); + """.formatted(localRepoPath) + ), ctx)); assertThat(ctx.getLocalRepository().getUri()) .startsWith("file://") .containsSubsequence(localRepoPath.toUri().toString().split("/")); @@ -392,7 +391,7 @@ void parsesLocalRepositoryPathFromSettingsXml(@TempDir Path localRepoPath) { @Test void parsesLocalRepositoryUriFromSettingsXml(@TempDir Path localRepoPath) { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ %s - """.formatted(localRepoPath).getBytes() - )), ctx)); + """.formatted(localRepoPath) + ), ctx)); assertThat(ctx.getLocalRepository().getUri()) .startsWith("file://") @@ -410,15 +409,15 @@ void parsesLocalRepositoryUriFromSettingsXml(@TempDir Path localRepoPath) { @Test void defaultsToTheMavenDefault() { - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); assertThat(ctx.getLocalRepository().getUri()).isEqualTo(MavenRepository.MAVEN_LOCAL_DEFAULT.getUri()); } @@ -430,7 +429,7 @@ class InterpolationTest { @Test void properties() { System.setProperty("rewrite.test.custom.location", "/tmp"); - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); assertThat(settings.getLocalRepository()).isEqualTo("/tmp/maven/local/repository/"); } @Test void unresolvedPlaceholdersRemainUnchanged() { - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); assertThat(settings.getLocalRepository()) .isEqualTo("${custom.location.zz}/maven/local/repository/"); @@ -516,7 +515,7 @@ void unresolvedPlaceholdersRemainUnchanged() { void env() { updateEnvMap("REWRITE_TEST_PRIVATE_REPO_USERNAME", "user"); updateEnvMap("REWRITE_TEST_PRIVATE_REPO_PASSWORD", "pass"); - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); assertThat(settings.getServers()).isNotNull(); assertThat(settings.getServers().getServers()).hasSize(1); @@ -621,9 +620,8 @@ class MergingTest { @Test void concatenatesElementsWithUniqueIds() { Path path = Paths.get("settings.xml"); - var baseSettings = MavenSettings.parse(new Parser.Input(path, () -> new ByteArrayInputStream( - installationSettings.getBytes())), ctx); - var userSettings = MavenSettings.parse(new Parser.Input(path, () -> new ByteArrayInputStream( + var baseSettings = MavenSettings.parse(Parser.Input.fromString(path, installationSettings), ctx); + var userSettings = MavenSettings.parse(Parser.Input.fromString(path, //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); var mergedSettings = userSettings.merge(baseSettings); @@ -681,9 +679,8 @@ void concatenatesElementsWithUniqueIds() { @Test void replacesElementsWithMatchingIds() { Path path = Paths.get("settings.xml"); - var baseSettings = MavenSettings.parse(new Parser.Input(path, () -> new ByteArrayInputStream( - installationSettings.getBytes())), ctx); - var userSettings = MavenSettings.parse(new Parser.Input(path, () -> new ByteArrayInputStream( + var baseSettings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), installationSettings), ctx); + var userSettings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx); + """ + ), ctx); var mergedSettings = userSettings.merge(baseSettings); @@ -742,7 +739,7 @@ void replacesElementsWithMatchingIds() { */ @Test void serverHttpHeaders() { - var settings = MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + var settings = MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ @@ -772,8 +769,8 @@ void serverHttpHeaders() { - """.getBytes() - )), ctx); + """ + ), ctx); MavenSettings.Server server = settings.getServers().getServers().get(0); assertThat(server.getConfiguration().getHttpHeaders().get(0).getName()).isEqualTo("X-JFrog-Art-Api"); diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java index fbd2f3c5a99..89bf27be4e8 100755 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java @@ -35,7 +35,6 @@ import org.openrewrite.maven.MavenSettings; import org.openrewrite.maven.tree.*; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.UnknownHostException; import java.nio.file.Files; @@ -46,10 +45,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; +import static java.util.Collections.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -94,7 +90,7 @@ void ossSonatype() { @Test void centralIdOverridesDefaultRepository() { var ctx = MavenExecutionContextView.view(this.ctx); - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ central - """.getBytes() - )), ctx)); + """ + ), ctx)); // Avoid actually trying to reach the made-up https://internalartifactrepository.yourorg.com for (MavenRepository repository : ctx.getRepositories()) { @@ -196,7 +192,7 @@ public void repositoryAccessFailed(String uri, Throwable e) { @Test void mirrorsOverrideRepositoriesInPom() { var ctx = MavenExecutionContextView.view(this.ctx); - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); Path pomPath = Paths.get("pom.xml"); Pom pom = Pom.builder() diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/search/FindRepositoryOrderTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/search/FindRepositoryOrderTest.java index 054038a2614..fe84bd472e8 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/search/FindRepositoryOrderTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/search/FindRepositoryOrderTest.java @@ -24,7 +24,6 @@ import org.openrewrite.maven.table.MavenRepositoryOrder; import org.openrewrite.test.RewriteTest; -import java.io.ByteArrayInputStream; import java.nio.file.Paths; import static org.assertj.core.api.Assertions.assertThat; @@ -36,7 +35,7 @@ class FindRepositoryOrderTest implements RewriteTest { @Test void findRepositoryOrder() { var ctx = MavenExecutionContextView.view(new InMemoryExecutionContext()); - ctx.setMavenSettings(MavenSettings.parse(new Parser.Input(Paths.get("settings.xml"), () -> new ByteArrayInputStream( + ctx.setMavenSettings(MavenSettings.parse(Parser.Input.fromString(Paths.get("settings.xml"), //language=xml """ - """.getBytes() - )), ctx)); + """ + ), ctx)); rewriteRun( spec -> spec diff --git a/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java b/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java index a1259aecdac..0351f635d24 100644 --- a/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java +++ b/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java @@ -32,7 +32,9 @@ import org.openrewrite.quark.Quark; import org.openrewrite.remote.Remote; import org.openrewrite.tree.ParseError; +import org.openrewrite.tree.ParsingExecutionContextView; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; @@ -628,7 +630,9 @@ default void rewriteRun(SourceSpec... sources) { } default ExecutionContext defaultExecutionContext(SourceSpec[] sourceSpecs) { - return new InMemoryExecutionContext(t -> fail("Failed to parse sources or run recipe", t)); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(t -> fail("Failed to parse sources or run recipe", t)); + ParsingExecutionContextView.view(ctx).setCharset(StandardCharsets.UTF_8); + return ctx; } @Override