From 2c4a05b1d5900c3fd15d7e3d9787a69bacfee7bc Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 17 Sep 2019 18:07:18 +0200 Subject: [PATCH] [jOOQ/jOOQ#9233] Use new Source API throughout the jOOQ API - LoaderSourceStep.loadCSV - LoaderSourceStep.loadJSON - LoaderSourceStep.loadXML --- .../main/java/org/jooq/LoaderSourceStep.java | 18 ++ jOOQ/src/main/java/org/jooq/Source.java | 135 ++++++++++++--- .../main/java/org/jooq/impl/LoaderImpl.java | 156 ++++++------------ 3 files changed, 183 insertions(+), 126 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/LoaderSourceStep.java b/jOOQ/src/main/java/org/jooq/LoaderSourceStep.java index 5b2f12e0a1..09e0e8b048 100644 --- a/jOOQ/src/main/java/org/jooq/LoaderSourceStep.java +++ b/jOOQ/src/main/java/org/jooq/LoaderSourceStep.java @@ -197,6 +197,12 @@ public interface LoaderSourceStep { @Support LoaderCSVStep loadCSV(Reader reader); + /** + * Load CSV data. + */ + @Support + LoaderCSVStep loadCSV(Source source); + /** * Load XML data. */ @@ -263,6 +269,12 @@ public interface LoaderSourceStep { @Support LoaderXMLStep loadXML(InputSource source); + /** + * Load XML data. + */ + @Support + LoaderXMLStep loadXML(Source source); + /** * Load JSON data. */ @@ -323,4 +335,10 @@ public interface LoaderSourceStep { @Support LoaderJSONStep loadJSON(Reader reader); + /** + * Load JSON data. + */ + @Support + LoaderJSONStep loadJSON(Source source); + } diff --git a/jOOQ/src/main/java/org/jooq/Source.java b/jOOQ/src/main/java/org/jooq/Source.java index 03daa75099..38b4411b4e 100644 --- a/jOOQ/src/main/java/org/jooq/Source.java +++ b/jOOQ/src/main/java/org/jooq/Source.java @@ -38,98 +38,183 @@ package org.jooq; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; +import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; + +import org.jooq.exception.IOException; /** * A source of text data. */ public final class Source { - private final String string; - private final byte[] bytes; - private final Charset charset; - private final Reader reader; - private final InputStream inputStream; + private final String string; + private final byte[] bytes; + private final String charsetName; + private final Charset charset; + private final CharsetDecoder charsetDecoder; + private final Reader reader; + private final InputStream inputStream; + private final File file; private Source( String string, byte[] bytes, + String charsetName, Charset charset, + CharsetDecoder charsetDecoder, Reader reader, - InputStream inputStream + InputStream inputStream, + File file ) { this.string = string; this.bytes = bytes; + this.charsetName = charsetName; this.charset = charset; + this.charsetDecoder = charsetDecoder; this.reader = reader; this.inputStream = inputStream; + this.file = file; } /** * Create a source from a string. */ public static final Source of(String string) { - return new Source(string, null, null, null, null); + return new Source(string, null, null, null, null, null, null, null); } /** * Create a source from binary data. */ public static final Source of(byte[] bytes) { - return new Source(null, bytes, null, null, null); + return of(bytes, (Charset) null); + } + + /** + * Create a source from binary data using a specific character set. + */ + public static final Source of(byte[] bytes, String charsetName) { + return new Source(null, bytes, charsetName, null, null, null, null, null); } /** * Create a source from binary data using a specific character set. */ public static final Source of(byte[] bytes, Charset charset) { - return new Source(null, bytes, charset, null, null); + return new Source(null, bytes, null, charset, null, null, null, null); + } + + /** + * Create a source from binary data using a specific character set. + */ + public static final Source of(byte[] bytes, CharsetDecoder charsetDecoder) { + return new Source(null, bytes, null, null, charsetDecoder, null, null, null); + } + + /** + * Create a source from a file. + */ + public static final Source of(File file) { + return new Source(null, null, null, null, null, null, null, file); + } + + /** + * Create a source from a file using a specific character set. + */ + public static final Source of(File file, String charsetName) { + return new Source(null, null, charsetName, null, null, null, null, file); + } + + /** + * Create a source from a file using a specific character set. + */ + public static final Source of(File file, Charset charset) { + return new Source(null, null, null, charset, null, null, null, file); + } + + /** + * Create a source from a file using a specific character set. + */ + public static final Source of(File file, CharsetDecoder charsetDecoder) { + return new Source(null, null, null, null, charsetDecoder, null, null, file); } /** * Create a source from a reader. */ public static final Source of(Reader reader) { - return new Source(null, null, null, reader, null); + return new Source(null, null, null, null, null, reader, null, null); } /** * Create a source from an input stream. */ public static final Source of(InputStream inputStream) { - return new Source(null, null, null, null, inputStream); + return new Source(null, null, null, null, null, null, inputStream, null); + } + + /** + * Create a source from an input stream using a specific character set. + */ + public static final Source of(InputStream inputStream, String charsetName) { + return new Source(null, null, charsetName, null, null, null, inputStream, null); } /** * Create a source from an input stream using a specific character set. */ public static final Source of(InputStream inputStream, Charset charset) { - return new Source(null, null, charset, null, inputStream); + return new Source(null, null, null, charset, null, null, inputStream, null); + } + + /** + * Create a source from an input stream using a specific character set. + */ + public static final Source of(InputStream inputStream, CharsetDecoder charsetDecoder) { + return new Source(null, null, null, null, charsetDecoder, null, inputStream, null); } /** * Produce a reader from this source. + * + * @throws IOException When something goes wrong creating a reader from this + * source. */ - public final Reader reader() { - if (string != null) - return new StringReader(string); - else if (bytes != null) - return inputStreamReader(new ByteArrayInputStream(bytes)); - else if (reader != null) - return reader; - else if (inputStream != null) - return inputStreamReader(inputStream); - else - throw new IllegalStateException("Could not produce a reader from this source"); + public final Reader reader() throws IOException { + try { + if (string != null) + return new StringReader(string); + else if (bytes != null) + return inputStreamReader(new ByteArrayInputStream(bytes)); + else if (reader != null) + return reader; + else if (inputStream != null) + return inputStreamReader(inputStream); + else if (file != null) + return inputStreamReader(new FileInputStream(file)); + else + throw new IllegalStateException("Could not produce a reader from this source"); + } + catch (java.io.IOException e) { + throw new IOException(e.getMessage(), e); + } } - private final Reader inputStreamReader(InputStream is) { - if (charset != null) + private final Reader inputStreamReader(InputStream is) throws UnsupportedEncodingException { + if (charsetName != null) + return new InputStreamReader(is, charsetName); + else if (charset != null) return new InputStreamReader(is, charset); + else if (charsetDecoder != null) + return new InputStreamReader(is, charsetDecoder); else return new InputStreamReader(is); } diff --git a/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java b/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java index b8436aee08..0882a0253d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java @@ -41,13 +41,9 @@ import static org.jooq.impl.Tools.EMPTY_FIELD; import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.sql.Connection; @@ -84,6 +80,7 @@ import org.jooq.LoaderXMLStep; import org.jooq.Record; import org.jooq.Result; import org.jooq.SelectQuery; +import org.jooq.Source; import org.jooq.Table; import org.jooq.exception.DataAccessException; import org.jooq.exception.LoaderConfigurationException; @@ -149,7 +146,7 @@ final class LoaderImpl implements private int bulk = BULK_NONE; private int bulkAfter = 1; private int content = CONTENT_CSV; - private final InputDelay data = new InputDelay(); + private Source input; private Iterator arrays; // CSV configuration data @@ -344,115 +341,109 @@ final class LoaderImpl implements @Override public final LoaderImpl loadCSV(File file) { - content = CONTENT_CSV; - data.file = file; - return this; + return loadCSV(Source.of(file)); } @Override public final LoaderImpl loadCSV(File file, String charsetName) { - data.charsetName = charsetName; - return loadCSV(file); + return loadCSV(Source.of(file, charsetName)); } @Override public final LoaderImpl loadCSV(File file, Charset cs) { - data.cs = cs; - return loadCSV(file); + return loadCSV(Source.of(file, cs)); } @Override public final LoaderImpl loadCSV(File file, CharsetDecoder dec) { - data.dec = dec; - return loadCSV(file); + return loadCSV(Source.of(file, dec)); } @Override public final LoaderImpl loadCSV(String csv) { - return loadCSV(new StringReader(csv)); + return loadCSV(Source.of(csv)); } @Override public final LoaderImpl loadCSV(InputStream stream) { - return loadCSV(new InputStreamReader(stream)); + return loadCSV(Source.of(stream)); } @Override - public final LoaderImpl loadCSV(InputStream stream, String charsetName) throws UnsupportedEncodingException { - return loadCSV(new InputStreamReader(stream, charsetName)); + public final LoaderImpl loadCSV(InputStream stream, String charsetName) { + return loadCSV(Source.of(stream, charsetName)); } @Override public final LoaderImpl loadCSV(InputStream stream, Charset cs) { - return loadCSV(new InputStreamReader(stream, cs)); + return loadCSV(Source.of(stream, cs)); } @Override public final LoaderImpl loadCSV(InputStream stream, CharsetDecoder dec) { - return loadCSV(new InputStreamReader(stream, dec)); + return loadCSV(Source.of(stream, dec)); } @Override public final LoaderImpl loadCSV(Reader reader) { + return loadCSV(Source.of(reader)); + } + + @Override + public final LoaderImpl loadCSV(Source s) { content = CONTENT_CSV; - data.reader = new BufferedReader(reader); + input = s; return this; } @Override public final LoaderImpl loadXML(File file) { - content = CONTENT_XML; - data.file = file; - return this; + return loadXML(Source.of(file)); } @Override public final LoaderImpl loadXML(File file, String charsetName) { - data.charsetName = charsetName; - return loadXML(file); + return loadXML(Source.of(file, charsetName)); } @Override public final LoaderImpl loadXML(File file, Charset cs) { - data.cs = cs; - return loadXML(file); + return loadXML(Source.of(file, cs)); } @Override public final LoaderImpl loadXML(File file, CharsetDecoder dec) { - data.dec = dec; - return loadXML(file); + return loadXML(Source.of(file, dec)); } @Override public final LoaderImpl loadXML(String xml) { - return loadXML(new StringReader(xml)); + return loadXML(Source.of(xml)); } @Override public final LoaderImpl loadXML(InputStream stream) { - return loadXML(new InputStreamReader(stream)); + return loadXML(Source.of(stream)); } @Override - public final LoaderImpl loadXML(InputStream stream, String charsetName) throws UnsupportedEncodingException { - return loadXML(new InputStreamReader(stream, charsetName)); + public final LoaderImpl loadXML(InputStream stream, String charsetName) { + return loadXML(Source.of(stream, charsetName)); } @Override public final LoaderImpl loadXML(InputStream stream, Charset cs) { - return loadXML(new InputStreamReader(stream, cs)); + return loadXML(Source.of(stream, cs)); } @Override public final LoaderImpl loadXML(InputStream stream, CharsetDecoder dec) { - return loadXML(new InputStreamReader(stream, dec)); + return loadXML(Source.of(stream, dec)); } @Override public final LoaderImpl loadXML(Reader reader) { - content = CONTENT_XML; - throw new UnsupportedOperationException("This is not yet implemented"); + return loadXML(Source.of(reader)); } @Override @@ -461,60 +452,67 @@ final class LoaderImpl implements throw new UnsupportedOperationException("This is not yet implemented"); } + @Override + public final LoaderImpl loadXML(Source s) { + content = CONTENT_XML; + input = s; + throw new UnsupportedOperationException("This is not yet implemented"); + } + @Override public final LoaderImpl loadJSON(File file) { - content = CONTENT_JSON; - data.file = file; - return this; + return loadJSON(Source.of(file)); } @Override public final LoaderImpl loadJSON(File file, String charsetName) { - data.charsetName = charsetName; - return loadJSON(file); + return loadJSON(Source.of(file, charsetName)); } @Override public final LoaderImpl loadJSON(File file, Charset cs) { - data.cs = cs; - return loadJSON(file); + return loadJSON(Source.of(file, cs)); } @Override public final LoaderImpl loadJSON(File file, CharsetDecoder dec) { - data.dec = dec; - return loadJSON(file); + return loadJSON(Source.of(file, dec)); } @Override public final LoaderImpl loadJSON(String json) { - return loadJSON(new StringReader(json)); + return loadJSON(Source.of(json)); } @Override public final LoaderImpl loadJSON(InputStream stream) { - return loadJSON(new InputStreamReader(stream)); + return loadJSON(Source.of(stream)); } @Override - public final LoaderImpl loadJSON(InputStream stream, String charsetName) throws UnsupportedEncodingException { - return loadJSON(new InputStreamReader(stream, charsetName)); + public final LoaderImpl loadJSON(InputStream stream, String charsetName) { + return loadJSON(Source.of(stream, charsetName)); } @Override public final LoaderImpl loadJSON(InputStream stream, Charset cs) { - return loadJSON(new InputStreamReader(stream, cs)); + return loadJSON(Source.of(stream, cs)); } @Override public final LoaderImpl loadJSON(InputStream stream, CharsetDecoder dec) { - return loadJSON(new InputStreamReader(stream, dec)); + return loadJSON(Source.of(stream, dec)); } @Override public final LoaderImpl loadJSON(Reader reader) { + return loadJSON(Source.of(reader)); + } + + @Override + public final LoaderImpl loadJSON(Source s) { content = CONTENT_JSON; - data.reader = new BufferedReader(reader); + input = s; return this; } @@ -652,7 +650,7 @@ final class LoaderImpl implements BufferedReader reader = null; try { - reader = data.reader(); + reader = new BufferedReader(input.reader()); Result r = new JSONReader(create).read(reader); source = r.fields(); @@ -678,11 +676,11 @@ final class LoaderImpl implements try { if (ignoreRows == 1) { - reader = new CSVReader(data.reader(), separator, quote, 0); + reader = new CSVReader(input.reader(), separator, quote, 0); source = Tools.fieldsByName(reader.next()); } else { - reader = new CSVReader(data.reader(), separator, quote, ignoreRows); + reader = new CSVReader(input.reader(), separator, quote, ignoreRows); } executeSQL(reader); @@ -995,48 +993,4 @@ final class LoaderImpl implements return stored; } } - - /** - * An "input delay" type. - *

- * [#4593] To make sure we do not spill file handles due to improper - * resource shutdown (e.g. when a loader is created but never executed), - * this type helps delaying creating resources from input until the input is - * really needed. - */ - private class InputDelay { - - // Either, we already have an external Reader resource, in case of which - // client code is responsible for resource management... - BufferedReader reader; - - // ... or we create the resource explicitly as late as possible - File file; - String charsetName; - Charset cs; - CharsetDecoder dec; - - BufferedReader reader() throws IOException { - if (reader != null) - return reader; - - if (file != null) { - try { - if (charsetName != null) - return new BufferedReader(new InputStreamReader(new FileInputStream(file), charsetName)); - else if (cs != null) - return new BufferedReader(new InputStreamReader(new FileInputStream(file), cs)); - else if (dec != null) - return new BufferedReader(new InputStreamReader(new FileInputStream(file), dec)); - else - return new BufferedReader(new InputStreamReader(new FileInputStream(file))); - } - catch (Exception e) { - throw new IOException(e); - } - } - - return null; - } - } }