This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 4078378df
org.apache.juneau.microservice.jetty.JettyMicroservice.Builder.jettyXml(Object,
boolean) now handles java.nio.file.Path.
4078378df is described below
commit 4078378dff0fe97f44dae6d27a7cb8b3649e72ed
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Jun 6 12:29:23 2025 -0400
org.apache.juneau.microservice.jetty.JettyMicroservice.Builder.jettyXml(Object,
boolean) now handles java.nio.file.Path.
- Add org.apache.juneau.common.internal.PathReaderBuilder
- Add org.apache.juneau.common.internal.IOUtils.read(Path)
---
RELEASE-NOTES.txt | 3 +
.../org/apache/juneau/common/internal/IOUtils.java | 86 +++++++++-----
.../juneau/common/internal/PathReaderBuilder.java | 125 +++++++++++++++++++++
.../microservice/jetty/JettyMicroservice.java | 18 +--
.../apache/juneau/common/internal/IOUtilsTest.java | 36 ++++++
.../common/internal/PathReaderBuilderTest.java | 116 +++++++++++++++++++
6 files changed, 352 insertions(+), 32 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 323e38eab..3e7618739 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -48,6 +48,9 @@ Release Notes - Juneau - Version 9.1.0
* Add org.apache.juneau.rest.mock.MockServletResponse.sendRedirect(String,
int, boolean) for jakarta.servlet:jakarta.servlet-api 6.1.0.
* Bump org.junit:junit-bom from 5.10.3 to 5.11.4 #161, #168, #171, #173,
#185.
* Flip console output logic on shutdown from a system property called
'SystemUtils.quiet' to 'SystemUtils.verbose'.
+ *
org.apache.juneau.microservice.jetty.JettyMicroservice.Builder.jettyXml(Object,
boolean) now handles java.nio.file.Path.
+ * Add org.apache.juneau.common.internal.PathReaderBuilder
+ * Add org.apache.juneau.common.internal.IOUtils.read(Path)
Release Notes - Juneau - Version 9.0.1
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/IOUtils.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/IOUtils.java
index 9c935a3eb..79aea8565 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/IOUtils.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/IOUtils.java
@@ -12,11 +12,24 @@
//
***************************************************************************************************************************
package org.apache.juneau.common.internal;
-import java.io.*;
-import java.nio.charset.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-import java.util.function.*;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Scanner;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
/**
* Various I/O related utility methods.
@@ -461,26 +474,49 @@ public final class IOUtils {
return new String(in, charset);
}
- /**
- * Reads the contents of a file into a string.
- *
- * <p>
- * Assumes default character encoding.
- *
- * @param in
- * The file to read.
- * <br>Can be <jk>null</jk>.
- * @return
- * The contents of the reader as a string, or <jk>null</jk> if
file does not exist.
- * @throws IOException If a problem occurred trying to read from the
reader.
- */
- public static String read(File in) throws IOException {
- if (in == null || ! in.exists())
- return null;
- try (Reader r = FileReaderBuilder.create(in).build()) {
- return read(r, in.length());
- }
- }
+ /**
+ * Reads the contents of a file into a string.
+ *
+ * <p>
+ * Assumes default character encoding.
+ *
+ * @param in
+ * The file to read.
+ * <br>Can be <jk>null</jk>.
+ * @return
+ * The contents of the reader as a string, or <jk>null</jk> if file does
not exist.
+ * @throws IOException If a problem occurred trying to read from the
reader.
+ */
+ public static String read(File in) throws IOException {
+ if (in == null || ! in.exists())
+ return null;
+ try (Reader r = FileReaderBuilder.create(in).build()) {
+ return read(r, in.length());
+ }
+ }
+
+ /**
+ * Reads the contents of a path into a string.
+ *
+ * <p>
+ * Assumes default character encoding.
+ *
+ * @param in
+ * The path to read.
+ * <br>Can be <jk>null</jk>.
+ * @return
+ * The contents of the reader as a string, or <jk>null</jk> if path does
not exist.
+ * @throws IOException If a problem occurred trying to read from the
reader.
+ * @since 9.1.0
+ */
+ public static String read(Path in) throws IOException {
+ if (in == null || !Files.exists(in)) {
+ return null;
+ }
+ try (Reader r = PathReaderBuilder.create(in).build()) {
+ return read(r, Files.size(in));
+ }
+ }
/**
* Reads the contents of a reader into a string.
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/PathReaderBuilder.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/PathReaderBuilder.java
new file mode 100644
index 000000000..c2c6bcb8a
--- /dev/null
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/PathReaderBuilder.java
@@ -0,0 +1,125 @@
+//
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
+// * with the License. You may obtain a copy of the License at
*
+// *
*
+// * http://www.apache.org/licenses/LICENSE-2.0
*
+// *
*
+// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
+// * specific language governing permissions and limitations under the
License. *
+//
***************************************************************************************************************************
+package org.apache.juneau.common.internal;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Utility class for creating {@link Path}-based {@link Reader} objects.
+ *
+ * @since 9.1.0
+ */
+public final class PathReaderBuilder {
+
+ /**
+ * Creates a new builder.
+ *
+ * @return A new builder.
+ */
+ public static PathReaderBuilder create() {
+ return new PathReaderBuilder();
+ }
+
+ /**
+ * Creates a new builder initialized with the specified path.
+ *
+ * @param path The path being written to.
+ * @return A new builder.
+ */
+ public static PathReaderBuilder create(final Path path) {
+ return new PathReaderBuilder().path(path);
+ }
+
+ private Path path;
+
+ private Charset charset = Charset.defaultCharset();
+
+ private boolean allowNoFile;
+
+ /**
+ * If called and the path is <jk>null</jk> or non-existent, then the
{@link #build()} command will return an empty reader instead of a {@link
IOException}.
+ *
+ * @return This object.
+ */
+ public PathReaderBuilder allowNoFile() {
+ this.allowNoFile = true;
+ return this;
+ }
+
+ /**
+ * Creates a new File reader.
+ *
+ * @return A new File reader.
+ * @throws IOException if an I/O error occurs opening the path
+ */
+ public Reader build() throws IOException {
+ if (!allowNoFile && path == null) {
+ throw new IllegalStateException("No path");
+ }
+ if (!allowNoFile && !Files.exists(path)) {
+ throw new NoSuchFileException(path.toString());
+ }
+ return allowNoFile ? new StringReader("") :
Files.newBufferedReader(path, charset != null ? charset :
Charset.defaultCharset());
+ }
+
+ /**
+ * Sets the character encoding of the path.
+ *
+ * @param charset The character encoding. The default is {@link
Charset#defaultCharset()}. Null resets to the default.
+ * @return This object.
+ */
+ public PathReaderBuilder charset(final Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ /**
+ * Sets the character encoding of the path.
+ *
+ * @param charset The character encoding. The default is {@link
Charset#defaultCharset()}. Null resets to the default.
+ * @return This object.
+ */
+ public PathReaderBuilder charset(final String charset) {
+ this.charset = charset != null ? Charset.forName(charset) : null;
+ return this;
+ }
+
+ /**
+ * Sets the path being written from.
+ *
+ * @param path The path being written from.
+ * @return This object.
+ */
+ public PathReaderBuilder path(final Path path) {
+ this.path = path;
+ return this;
+ }
+
+ /**
+ * Sets the path of the path being written from.
+ *
+ * @param path The path of the path being written from.
+ * @return This object.
+ */
+ public PathReaderBuilder path(final String path) {
+ this.path = Paths.get(path);
+ return this;
+ }
+}
diff --git
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
index ccc9890a7..261d0bebc 100644
---
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
+++
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
@@ -30,6 +30,7 @@ import java.net.ServerSocket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
+import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
@@ -203,7 +204,8 @@ public class JettyMicroservice extends Microservice {
* <br>Can be any of the following:
* <ul>
* <li>{@link String} - Relative path to file on
file system or classpath.
- * <li>{@link File} - File on file system.
+ * <li>{@link File} - File on file system.
+ * <li>{@link Path} - Path on file system.
* <li>{@link InputStream} - Raw contents as
<c>UTF-8</c> encoded stream.
* <li>{@link Reader} - Raw contents.
* </ul>
@@ -216,12 +218,14 @@ public class JettyMicroservice extends Microservice {
public Builder jettyXml(Object jettyXml, boolean resolveVars)
throws IOException {
if (jettyXml instanceof String)
this.jettyXml =
read(resolveFile(jettyXml.toString()));
- else if (jettyXml instanceof File)
- this.jettyXml = read((File)jettyXml);
- else if (jettyXml instanceof InputStream)
- this.jettyXml = read((InputStream)jettyXml);
- else if (jettyXml instanceof Reader)
- this.jettyXml = read((Reader)jettyXml);
+ else if (jettyXml instanceof File file)
+ this.jettyXml = read(file);
+ else if (jettyXml instanceof Path path)
+ this.jettyXml = read(path);
+ else if (jettyXml instanceof InputStream inputStream)
+ this.jettyXml = read(inputStream);
+ else if (jettyXml instanceof Reader reader)
+ this.jettyXml = read(reader);
else
throw new BasicRuntimeException("Invalid object
type passed to jettyXml(Object): {0}", className(jettyXml));
this.jettyXmlResolveVars = resolveVars;
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/internal/IOUtilsTest.java
b/juneau-utest/src/test/java/org/apache/juneau/common/internal/IOUtilsTest.java
new file mode 100644
index 000000000..c2dedf9a1
--- /dev/null
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/internal/IOUtilsTest.java
@@ -0,0 +1,36 @@
+//
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
+// * with the License. You may obtain a copy of the License at
*
+// *
*
+// * http://www.apache.org/licenses/LICENSE-2.0
*
+// *
*
+// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
+// * specific language governing permissions and limitations under the
License. *
+//
***************************************************************************************************************************
+
+package org.apache.juneau.common.internal;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.file.Paths;
+import java.util.Properties;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link IOUtils}.
+ */
+public class IOUtilsTest {
+
+ @Test
+ public void testReadPath() throws IOException {
+ var p = new Properties();
+ p.load(new
StringReader(IOUtils.read(Paths.get("src/test/resources/files/Test3.properties"))));
+ assertEquals("files/Test3.properties", p.get("file"));
+ }
+}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/internal/PathReaderBuilderTest.java
b/juneau-utest/src/test/java/org/apache/juneau/common/internal/PathReaderBuilderTest.java
new file mode 100644
index 000000000..ad9d6f142
--- /dev/null
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/internal/PathReaderBuilderTest.java
@@ -0,0 +1,116 @@
+//
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
+// * with the License. You may obtain a copy of the License at
*
+// *
*
+// * http://www.apache.org/licenses/LICENSE-2.0
*
+// *
*
+// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
+// * specific language governing permissions and limitations under the
License. *
+//
***************************************************************************************************************************
+
+package org.apache.juneau.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Properties;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link PathReaderBuilder}.
+ */
+public class PathReaderBuilderTest {
+
+ private static final Path PATH =
Paths.get("src/test/resources/files/Test3.properties");
+
+ @Test
+ public void testAllowNoFile() throws IOException {
+ final var p = new Properties();
+ try (Reader r = PathReaderBuilder.create().allowNoFile().build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertNull(p.get("file"));
+ p.clear();
+ try (Reader r = PathReaderBuilder.create().allowNoFile().path("this
file does not exist, at all.").build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertNull(p.get("file"));
+ }
+
+ @Test
+ public void testAllowNoFileException() throws IOException {
+ final var p = new Properties();
+ assertThrows(IllegalStateException.class, () ->
PathReaderBuilder.create().build());
+ assertThrows(NoSuchFileException.class, () ->
PathReaderBuilder.create().path("this file does not exist, at all.").build());
+ }
+
+ @Test
+ public void testCharsetCharset() throws IOException {
+ final var p = new Properties();
+ try (Reader r =
PathReaderBuilder.create().path(PATH).charset(StandardCharsets.UTF_8).build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ p.clear();
+ try (Reader r =
PathReaderBuilder.create().path(PATH).charset((Charset) null).build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ }
+
+ @Test
+ public void testCharsetString() throws IOException {
+ final var p = new Properties();
+ try (Reader r =
PathReaderBuilder.create().path(PATH).charset(StandardCharsets.UTF_8.name()).build())
{
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ p.clear();
+ try (Reader r = PathReaderBuilder.create().path(PATH).charset((String)
null).build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ }
+
+ @Test
+ public void testCreate() throws IOException {
+ final var p = new Properties();
+ try (Reader r = PathReaderBuilder.create(PATH).build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ }
+
+ @Test
+ public void testPathPath() throws IOException {
+ final var p = new Properties();
+ try (Reader r = PathReaderBuilder.create().path(PATH).build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ }
+
+ @Test
+ public void testPathString() throws IOException {
+ final var p = new Properties();
+ try (Reader r =
PathReaderBuilder.create().path(PATH.toString()).build()) {
+ p.load(new StringReader(IOUtils.read(r, Files.size(PATH))));
+ }
+ assertEquals("files/Test3.properties", p.get("file"));
+ }
+
+}