This is an automated email from the ASF dual-hosted git repository. sgoeschl pushed a commit to branch FREEMARKER-172 in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git
commit f66424443b62d9784491111db94b12fe0789c481 Author: Siegfried Goeschl <[email protected]> AuthorDate: Wed Feb 3 20:39:03 2021 +0100 FREEMARKER-172 [freemarker-generator] Start with refactoring --- .../base/datasource/DataSourceFactory.java | 138 ++++----------------- .../datasource/loader/FileDataSourceLoader.java | 4 +- .../template/TemplateTransformationsBuilder.java | 9 +- .../datasource/DataSourceFactoryTest.java | 74 ++--------- .../generator/datasource/DataSourceTest.java | 8 +- .../generator/datasource/DataSourcesTest.java | 81 +++++++----- 6 files changed, 92 insertions(+), 222 deletions(-) diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceFactory.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceFactory.java index 30e3c7a..47e5d46 100644 --- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceFactory.java +++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/DataSourceFactory.java @@ -17,15 +17,11 @@ package org.apache.freemarker.generator.base.datasource; import org.apache.freemarker.generator.base.FreeMarkerConstants.Location; -import org.apache.freemarker.generator.base.activation.ByteArrayDataSource; import org.apache.freemarker.generator.base.activation.CachingUrlDataSource; import org.apache.freemarker.generator.base.activation.InputStreamDataSource; import org.apache.freemarker.generator.base.activation.StringDataSource; import org.apache.freemarker.generator.base.mime.MimetypesFileTypeMapFactory; -import org.apache.freemarker.generator.base.uri.NamedUri; -import org.apache.freemarker.generator.base.uri.NamedUriStringParser; import org.apache.freemarker.generator.base.util.PropertiesFactory; -import org.apache.freemarker.generator.base.util.StringUtils; import org.apache.freemarker.generator.base.util.UriUtils; import org.apache.freemarker.generator.base.util.Validate; @@ -44,61 +40,26 @@ import java.util.UUID; import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.freemarker.generator.base.FreeMarkerConstants.DEFAULT_GROUP; -import static org.apache.freemarker.generator.base.mime.Mimetypes.MIME_TEXT_PLAIN; -import static org.apache.freemarker.generator.base.util.StringUtils.firstNonEmpty; /** - * Creates a FreeMarker data source from various sources. + * Low-level factory to create FreeMarker data sources. */ public abstract class DataSourceFactory { - private static final String NO_MIME_TYPE = null; - private static final Charset NO_CHARSET = null; - private static final String ROOT_DIR = "/"; - private DataSourceFactory() { } - // == NamedUri ========================================================== - - public static DataSource fromNamedUri(String str) { - Validate.notNull(str, "namedUri is null"); - - return fromNamedUri(NamedUriStringParser.parse(str)); - } + // == General =========================================================== - public static DataSource fromNamedUri(NamedUri namedUri) { - Validate.notNull(namedUri, "namedUri is null"); - - final URI uri = namedUri.getUri(); - final String group = namedUri.getGroupOrElse(DEFAULT_GROUP); - final Charset charset = getCharsetOrElse(namedUri, NO_CHARSET); - final String mimeType = getMimeTypeOrElse(namedUri, NO_MIME_TYPE); - - if (UriUtils.isHttpUri(uri)) { - final URL url = toUrl(uri); - final String name = namedUri.getNameOrElse(UriUtils.toStringWithoutFragment(uri)); - return fromUrl(name, group, url, mimeType, charset); - } else if (UriUtils.isFileUri(uri)) { - final File file = namedUri.getFile(); - final String name = namedUri.getNameOrElse(UriUtils.toStringWithoutFragment(file.toURI())); - return fromFile(name, group, file, charset); - } else if (UriUtils.isEnvUri(uri)) { - // environment variables come with a leading "/" to be removed - final String key = stripRootDir(uri.getPath()); - final String contentType = getMimeTypeOrElse(namedUri, MIME_TEXT_PLAIN); - final String name = firstNonEmpty(namedUri.getName(), key, Location.ENVIRONMENT); - if (StringUtils.isEmpty(key)) { - return fromEnvironment(name, group, contentType); - } else { - return fromEnvironment(name, group, key, contentType); - } - } else { - // handle things such as "foo=some.file" - final File file = namedUri.getFile(); - final String name = namedUri.getNameOrElse(UriUtils.toStringWithoutFragment(file.toURI())); - return fromFile(name, group, file, charset); - } + public static DataSource create( + String name, + String group, + URI uri, + javax.activation.DataSource dataSource, + String contentType, + Charset charset + ) { + return new DataSource(name, group, uri, dataSource, contentType, charset); } // == URL =============================================================== @@ -132,23 +93,16 @@ public abstract class DataSourceFactory { return create(name, group, file.toURI(), dataSource, contentType, charset); } - // == Bytes ============================================================ - - public static DataSource fromBytes(String name, String group, byte[] content, String contentType) { - final ByteArrayDataSource dataSource = new ByteArrayDataSource(name, content); - final URI uri = UriUtils.toUri(Location.BYTES + ":///"); - return create(name, group, uri, dataSource, contentType, UTF_8); - } - // == InputStream ======================================================= - public static DataSource fromInputStream(String name, String group, InputStream is, String contentType, Charset charset) { - final InputStreamDataSource dataSource = new InputStreamDataSource(name, is); - final URI uri = UriUtils.toUri(Location.INPUTSTREAM + ":///"); - return create(name, group, uri, dataSource, contentType, charset); - } - - public static DataSource fromInputStream(String name, String group, URI uri, InputStream is, String contentType, Charset charset) { + public static DataSource fromInputStream( + String name, + String group, + URI uri, + InputStream is, + String contentType, + Charset charset + ) { final InputStreamDataSource dataSource = new InputStreamDataSource(name, is); return create(name, group, uri, dataSource, contentType, charset); } @@ -176,60 +130,12 @@ public abstract class DataSourceFactory { return create(name, group, uri, dataSource, contentType, UTF_8); } - // == General =========================================================== - - /** - * Create a data source based on a - * <ul> - * <li>URI</li> - * <li>Named URI</li> - * <li>file name</li> - * </ul> - * - * @param source source of the data source - * @return DataSource - */ - public static DataSource create(String source) { - if (UriUtils.isUri(source)) { - return fromNamedUri(source); - } else { - final File file = new File(source); - return fromFile(file.getName(), DEFAULT_GROUP, file, UTF_8); - } - } - - public static DataSource create( - String name, - String group, - URI uri, - javax.activation.DataSource dataSource, - String contentType, - Charset charset) { - return new DataSource(name, group, uri, dataSource, contentType, charset); - } - - private static String getMimeTypeOrElse(NamedUri namedUri, String def) { - return namedUri.getParameter(NamedUri.MIMETYPE, def); - } - - private static Charset getCharsetOrElse(NamedUri namedUri, Charset def) { - final String charsetName = namedUri.getParameter(NamedUri.CHARSET); - return StringUtils.isEmpty(charsetName) ? def : Charset.forName(charsetName); - } - - private static URL toUrl(URI uri) { + public static URL toUrl(String url) { try { - return uri.toURL(); + return new URL(url); } catch (MalformedURLException e) { - throw new IllegalArgumentException(uri.toString(), e); + throw new IllegalArgumentException(url, e); } } - private static String stripRootDir(String str) { - if (str.startsWith(ROOT_DIR)) { - return str.substring(ROOT_DIR.length()); - } else { - return str; - } - } } diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/loader/FileDataSourceLoader.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/loader/FileDataSourceLoader.java index fd2f576..f76cb88 100644 --- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/loader/FileDataSourceLoader.java +++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/datasource/loader/FileDataSourceLoader.java @@ -43,7 +43,9 @@ public class FileDataSourceLoader implements DataSourceLoader { final String group = namedUri.getGroupOrElse(FreeMarkerConstants.DEFAULT_GROUP); final Charset charset = namedUri.getCharsetOrElse(UTF_8); final File file = namedUri.getFile(); - final String name = namedUri.getNameOrElse(UriUtils.toStringWithoutFragment(file.toURI())); + // TODO + // final String name = namedUri.getNameOrElse(UriUtils.toStringWithoutFragment(file.toURI())); + final String name = namedUri.getNameOrElse(file.getName()); return DataSourceFactory.fromFile(name, group, file, charset); } diff --git a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/template/TemplateTransformationsBuilder.java b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/template/TemplateTransformationsBuilder.java index 6aaf494..c8541d8 100644 --- a/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/template/TemplateTransformationsBuilder.java +++ b/freemarker-generator-base/src/main/java/org/apache/freemarker/generator/base/template/TemplateTransformationsBuilder.java @@ -18,7 +18,8 @@ package org.apache.freemarker.generator.base.template; import org.apache.freemarker.generator.base.FreeMarkerConstants.Location; import org.apache.freemarker.generator.base.datasource.DataSource; -import org.apache.freemarker.generator.base.datasource.DataSourceFactory; +import org.apache.freemarker.generator.base.datasource.DataSourceLoader; +import org.apache.freemarker.generator.base.datasource.DataSourceLoaderFactory; import org.apache.freemarker.generator.base.file.RecursiveFileSupplier; import org.apache.freemarker.generator.base.util.NonClosableWriterWrapper; import org.apache.freemarker.generator.base.util.StringUtils; @@ -41,6 +42,8 @@ import static java.util.Collections.singletonList; */ public class TemplateTransformationsBuilder { + private final DataSourceLoader dataSourceLoader; + /** Interactive template */ private TemplateSource interactiveTemplate; @@ -66,6 +69,7 @@ public class TemplateTransformationsBuilder { private Writer callerSuppliedWriter; private TemplateTransformationsBuilder() { + this.dataSourceLoader = DataSourceLoaderFactory.create(); this.templateSource = null; this.includes = new ArrayList<>(); this.excludes = new ArrayList<>(); @@ -228,7 +232,7 @@ public class TemplateTransformationsBuilder { } private TemplateSource templateSource(String source) { - try (DataSource dataSource = DataSourceFactory.create(source)) { + try (DataSource dataSource = dataSourceLoader.load(source)) { return TemplateSource.fromCode(dataSource.getName(), dataSource.getText(templateEncoding.name())); } } @@ -300,4 +304,5 @@ public class TemplateTransformationsBuilder { // avoid closing System.out after rendering the template return new BufferedWriter(new NonClosableWriterWrapper(new OutputStreamWriter(System.out, outputEncoding))); } + } diff --git a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceFactoryTest.java b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceFactoryTest.java index 0610e2d..85dc86c 100644 --- a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceFactoryTest.java +++ b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceFactoryTest.java @@ -17,10 +17,10 @@ package org.apache.freemarker.generator.datasource; import org.apache.commons.io.FilenameUtils; +import org.apache.freemarker.generator.base.FreeMarkerConstants.Location; import org.apache.freemarker.generator.base.datasource.DataSource; import org.apache.freemarker.generator.base.datasource.DataSourceFactory; -import org.apache.freemarker.generator.base.uri.NamedUri; -import org.apache.freemarker.generator.base.uri.NamedUriStringParser; +import org.apache.freemarker.generator.base.util.UriUtils; import org.junit.Ignore; import org.junit.Test; @@ -28,6 +28,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URI; import java.net.URL; import java.nio.charset.Charset; @@ -46,7 +47,7 @@ public class DataSourceFactoryTest { private static final String ANY_FILE_URI = format("file:///%s/pom.xml", PWD); private static final Charset ANY_CHAR_SET = UTF_8; private static final File ANY_FILE = new File(ANY_FILE_NAME); - private static final String ANY_ENV_VARIABLE = "JAVA_HOME"; + private static final String ANY_ENV_VARIABLE = "HOME"; private static final String ANY_NAMED_URL_STRING = "content:www=https://www.google.com?foo=bar#contenttype=application/json"; @Test @@ -61,17 +62,6 @@ public class DataSourceFactoryTest { } @Test - public void shouldCreateDataSourceFromFileUri() { - final DataSource dataSource = DataSourceFactory.create(ANY_FILE_URI); - - assertEquals(ANY_FILE_NAME, dataSource.getFileName()); - assertEquals(UTF_8, dataSource.getCharset()); - assertEquals(MIME_APPLICATION_XML, dataSource.getContentType()); - assertEquals(ANY_FILE.toURI(), dataSource.getUri()); - assertTrue(!dataSource.getLines().isEmpty()); - } - - @Test public void shouldCreateDataSourceFromString() { final DataSource dataSource = DataSourceFactory.fromString("test.txt", "default", ANY_TEXT, "text/plain"); @@ -85,22 +75,10 @@ public class DataSourceFactoryTest { } @Test - public void shouldCreateDataSourceFromBytes() { - final DataSource dataSource = DataSourceFactory.fromBytes("test.txt", "default", ANY_TEXT.getBytes(UTF_8), "text/plain"); - - assertEquals("test.txt", dataSource.getName()); - assertEquals("default", dataSource.getGroup()); - assertEquals(UTF_8, dataSource.getCharset()); - assertEquals("text/plain", dataSource.getContentType()); - assertTrue(dataSource.getUri().toString().startsWith("bytes:///")); - assertEquals(ANY_TEXT, dataSource.getText()); - assertEquals(1, dataSource.getLines().size()); - } - - @Test public void shouldCreateDataSourceFromInputStream() { + final URI uri = UriUtils.toUri(Location.INPUTSTREAM + ":///"); final InputStream is = new ByteArrayInputStream(ANY_TEXT.getBytes(UTF_8)); - final DataSource dataSource = DataSourceFactory.fromInputStream("test.txt", "default", is, "text/plain", UTF_8); + final DataSource dataSource = DataSourceFactory.fromInputStream("test.txt", "default", uri, is, "text/plain", UTF_8); assertEquals("test.txt", dataSource.getName()); assertEquals(UTF_8, dataSource.getCharset()); @@ -116,26 +94,14 @@ public class DataSourceFactoryTest { final DataSource dataSource = DataSourceFactory.fromUrl("jsonplaceholder.typicode.com", "default", url, null, null); assertEquals("jsonplaceholder.typicode.com", dataSource.getName()); + assertEquals("jsonplaceholder.typicode.com", dataSource.getFileName()); assertEquals("application/json", dataSource.getContentType()); assertEquals(UTF_8, dataSource.getCharset()); } @Test - @Ignore - public void shouldCreateDataSourceFromNamedURL() { - final NamedUri namedUri = NamedUriStringParser.parse(ANY_NAMED_URL_STRING); - final DataSource dataSource = DataSourceFactory.fromNamedUri(namedUri); - - assertEquals(namedUri.getName(), dataSource.getName()); - assertEquals(namedUri.getGroup(), dataSource.getGroup()); - assertEquals("ISO-8859-1", dataSource.getCharset().toString()); - assertEquals(namedUri.getUri().toString(), dataSource.getUri().toString()); - } - - @Test public void shouldCreateDataSourceFromEnvironment() { - final NamedUri namedUri = NamedUriStringParser.parse("env:///"); - final DataSource dataSource = DataSourceFactory.fromNamedUri(namedUri); + final DataSource dataSource = DataSourceFactory.fromEnvironment("env", "default", "text/plain"); assertEquals("env", dataSource.getName()); assertEquals("default", dataSource.getGroup()); @@ -144,28 +110,4 @@ public class DataSourceFactoryTest { assertEquals("text/plain", dataSource.getContentType()); } - @Test - public void shouldCreateDataSourceFromNamedEnvironment() { - final NamedUri namedUri = NamedUriStringParser.parse("config=env:///"); - final DataSource dataSource = DataSourceFactory.fromNamedUri(namedUri); - - assertEquals("config", dataSource.getName()); - assertEquals("default", dataSource.getGroup()); - assertEquals(UTF_8, dataSource.getCharset()); - assertEquals("env:///", dataSource.getUri().toString()); - assertEquals("text/plain", dataSource.getContentType()); - } - - @Test - public void shouldCreateDataSourceFromEnvironmentVariable() { - final String uri = "env:///" + ANY_ENV_VARIABLE; - final NamedUri namedUri = NamedUriStringParser.parse("myenv=" + uri); - final DataSource dataSource = DataSourceFactory.fromNamedUri(namedUri); - - assertEquals("myenv", dataSource.getName()); - assertEquals("default", dataSource.getGroup()); - assertEquals(UTF_8, dataSource.getCharset()); - assertEquals(uri, dataSource.getUri().toString()); - assertEquals("text/plain", dataSource.getContentType()); - } } diff --git a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceTest.java b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceTest.java index 155b778..3f26014 100644 --- a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceTest.java +++ b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceTest.java @@ -20,7 +20,6 @@ import org.apache.commons.io.LineIterator; import org.apache.freemarker.generator.base.datasource.DataSource; import org.apache.freemarker.generator.base.datasource.DataSourceFactory; import org.apache.freemarker.generator.base.mime.Mimetypes; -import org.junit.Ignore; import org.junit.Test; import java.io.Closeable; @@ -31,6 +30,7 @@ import java.util.Iterator; import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.freemarker.generator.base.FreeMarkerConstants.DEFAULT_GROUP; +import static org.apache.freemarker.generator.base.datasource.DataSourceFactory.toUrl; import static org.apache.freemarker.generator.base.mime.Mimetypes.MIME_TEXT_HTML; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -80,10 +80,10 @@ public class DataSourceTest { } } - @Ignore("Requires internet connection") + // @Ignore("Requires internet connection") @Test public void shouldSupportUrlDataSource() { - try (DataSource dataSource = DataSourceFactory.create("https://www.google.com/?foo=bar")) { + try (DataSource dataSource = DataSourceFactory.fromUrl("www.google.com", DEFAULT_GROUP, toUrl("https://www.google.com/?foo=bar"), null, null)) { assertEquals("www.google.com", dataSource.getName()); assertEquals(DEFAULT_GROUP, dataSource.getGroup()); assertEquals("www.google", dataSource.getBaseName()); @@ -157,5 +157,7 @@ public class DataSourceTest { public boolean isClosed() { return closed; } + } + } diff --git a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java index d3cdf45..a8659dc 100644 --- a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java +++ b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourcesTest.java @@ -22,6 +22,8 @@ import org.apache.freemarker.generator.base.datasource.DataSources; import org.junit.Test; import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Arrays.asList; @@ -43,37 +45,38 @@ public class DataSourcesTest { @Test public void shouldFindByName() { - final DataSources dataSources = dataSources(); - - assertEquals(0, dataSources.find(null).size()); - assertEquals(0, dataSources.find("").size()); - assertEquals(0, dataSources.find("*.bar").size()); - assertEquals(0, dataSources.find("foo.*").size()); - assertEquals(0, dataSources.find("foo.bar").size()); - - assertEquals(2, dataSources.find("*.*").size()); - assertEquals(1, dataSources.find("*." + ANY_FILE_EXTENSION).size()); - assertEquals(1, dataSources.find("*/*." + ANY_FILE_EXTENSION).size()); - assertEquals(1, dataSources.find("*.???").size()); - assertEquals(1, dataSources.find("*om*").size()); - assertEquals(1, dataSources.find("*o*.xml").size()); - - assertEquals(3, dataSources.find("*").size()); + try (DataSources dataSources = dataSources()) { + assertEquals(0, dataSources.find(null).size()); + assertEquals(0, dataSources.find("").size()); + assertEquals(0, dataSources.find("*.bar").size()); + assertEquals(0, dataSources.find("foo.*").size()); + assertEquals(0, dataSources.find("foo.bar").size()); + + assertEquals(2, dataSources.find("*.*").size()); + assertEquals(1, dataSources.find("*." + ANY_FILE_EXTENSION).size()); + assertEquals(1, dataSources.find("*/*." + ANY_FILE_EXTENSION).size()); + assertEquals(1, dataSources.find("*.???").size()); + assertEquals(1, dataSources.find("*om*").size()); + assertEquals(1, dataSources.find("*o*.xml").size()); + + assertEquals(3, dataSources.find("*").size()); + } } @Test public void shouldFindByGroupPart() { - final DataSources dataSources = dataSources(); + try (DataSources dataSources = dataSources()) { - assertEquals(0, dataSources.find(GROUP_PART, null).size()); - assertEquals(0, dataSources.find(GROUP_PART, "").size()); + assertEquals(0, dataSources.find(GROUP_PART, null).size()); + assertEquals(0, dataSources.find(GROUP_PART, "").size()); - assertEquals(0, dataSources.find(GROUP_PART, "unknown").size()); + assertEquals(0, dataSources.find(GROUP_PART, "unknown").size()); - assertEquals(3, dataSources.find(GROUP_PART, "*").size()); - assertEquals(3, dataSources.find(GROUP_PART, "default").size()); - assertEquals(3, dataSources.find(GROUP_PART, "d*").size()); - assertEquals(3, dataSources.find(GROUP_PART, "d??????").size()); + assertEquals(3, dataSources.find(GROUP_PART, "*").size()); + assertEquals(3, dataSources.find(GROUP_PART, "default").size()); + assertEquals(3, dataSources.find(GROUP_PART, "d*").size()); + assertEquals(3, dataSources.find(GROUP_PART, "d??????").size()); + } } @@ -84,15 +87,16 @@ public class DataSourcesTest { @Test public void shouldGetAllDataSource() { - final DataSources dataSources = dataSources(); - - assertEquals("unknown", dataSources.get(0).getFileName()); - assertEquals("pom.xml", dataSources.get(1).getFileName()); - assertEquals("server.invalid?foo=bar", dataSources.get(2).getFileName()); - assertEquals(3, dataSources.toList().size()); - assertEquals(3, dataSources.toMap().size()); - assertEquals(3, dataSources.size()); - assertFalse(dataSources.isEmpty()); + try (DataSources dataSources = dataSources()) { + + assertEquals("unknown", dataSources.get(0).getFileName()); + assertEquals("pom.xml", dataSources.get(1).getFileName()); + assertEquals("server.invalid?foo=bar", dataSources.get(2).getFileName()); + assertEquals(3, dataSources.toList().size()); + assertEquals(3, dataSources.toMap().size()); + assertEquals(3, dataSources.size()); + assertFalse(dataSources.isEmpty()); + } } @Test @@ -133,6 +137,15 @@ public class DataSourcesTest { } private static DataSource urlDataSource() { - return DataSourceFactory.create(ANY_URL); + return DataSourceFactory.fromUrl("server.invalid?foo=bar", "default", toUrl(ANY_URL), "plain/text", UTF_8); } + + private static URL toUrl(String value) { + try { + return new URL(value); + } catch (MalformedURLException e) { + throw new RuntimeException("Failed to create URL:" + value, e); + } + } + }
