Mercurial > hg > monetdb-java
diff src/main/java/org/monetdb/jdbc/MonetConnection.java @ 514:443780d71bae onclient
More renaming. user registers MonetUploadHandler which is handed an Upload
author | Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com> |
---|---|
date | Mon, 23 Aug 2021 09:42:58 +0200 (2021-08-23) |
parents | bd860e850fe1 |
children | 7bbcff2c775b |
line wrap: on
line diff
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java @@ -8,10 +8,10 @@ package org.monetdb.jdbc; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.net.SocketException; import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -152,8 +152,8 @@ public class MonetConnection private DatabaseMetaData dbmd; /** Handlers for ON CLIENT requests */ - private MonetUploader uploader; - private MonetDownloader downloader; + private MonetUploadHandler uploader; + private MonetDownloadHandler downloader; /** * Constructor of a Connection for MonetDB. At this moment the @@ -1200,31 +1200,31 @@ public class MonetConnection /** * Registers a MonetUploader to support for example COPY ON CLIENT * - * @param uploader the handler to register, or null to deregister + * @param uploadHandler the handler to register, or null to deregister */ - public void setUploader(MonetUploader uploader) { - this.uploader = uploader; + public void setUploadHandler(MonetUploadHandler uploadHandler) { + this.uploader = uploadHandler; } /** * Returns the currently registerered MonetUploader, or null */ - public MonetUploader getUploader() { + public MonetUploadHandler getUploadHandler() { return uploader; } /** * Registers a MonetDownloader to support for example COPY ON CLIENT * - * @param downloader the handler to register, or null to deregister + * @param downloadHandler the handler to register, or null to deregister */ - public void setDownloader(MonetDownloader downloader) { - this.downloader = downloader; + public void setDownloadHandler(MonetDownloadHandler downloadHandler) { + this.downloader = downloadHandler; } /** * Returns the currently registerered MonetDownloadHandler handler, or null */ - public MonetDownloader getDownloader() { + public MonetDownloadHandler getDownloadHandler() { return downloader; } @@ -3232,7 +3232,7 @@ public class MonetConnection return "No file upload handler has been registered with the JDBC driver"; } - MonetUploadHandle handle = new MonetUploadHandle(server); + Upload handle = new Upload(server); boolean wasFaking = server.setInsertFakePrompts(false); try { uploader.handleUpload(handle, path, textMode, offset); @@ -3253,7 +3253,7 @@ public class MonetConnection return "No file download handler has been registered with the JDBC driver"; } - MonetDownloadHandle handle = new MonetDownloadHandle(server); + Download handle = new Download(server); downloader.handleDownload(handle, path, true); if (!handle.hasBeenUsed()) { String message = String.format("Call to %s.handleDownload for path '%s' sent neither data nor an error message", @@ -3263,4 +3263,140 @@ public class MonetConnection handle.close(); return handle.getError(); } + + public static class Upload { + private final MapiSocket server; + private PrintStream print = null; + private String error = null; + + Upload(MapiSocket server) { + this.server = server; + } + + public void sendError(String errorMessage) throws IOException { + if (error != null) { + throw new IOException("another error has already been sent: " + error); + } + error = errorMessage; + } + + public PrintStream getStream() throws IOException { + if (error != null) { + throw new IOException("Cannot send data after an error has been sent"); + } + if (print == null) { + try { + MapiSocket.UploadStream up = server.uploadStream(); + print = new PrintStream(up, false, "UTF-8"); + up.write('\n'); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("The system is guaranteed to support the UTF-8 encoding but apparently it doesn't", e); + } + } + return print; + } + + public boolean hasBeenUsed() { + return print != null || error != null; + } + + public String getError() { + return error; + } + + public void uploadFrom(InputStream inputStream) throws IOException { + OutputStream s = getStream(); + byte[] buffer = new byte[64 * 1024]; + while (true) { + int nread = inputStream.read(buffer); + if (nread < 0) { + break; + } + s.write(buffer, 0, nread); + } + } + + public void uploadFrom(BufferedReader reader, int offset) throws IOException { + // we're 1-based but also accept 0 + if (offset > 0) { + offset -= 1; + } + + for (int i = 0; i < offset; i++) { + String line = reader.readLine(); + if (line == null) { + return; + } + } + + uploadFrom(reader); + } + + public void uploadFrom(BufferedReader reader) throws IOException { + OutputStream s = getStream(); + OutputStreamWriter writer = new OutputStreamWriter(s, StandardCharsets.UTF_8); + char[] buffer = new char[64 * 1024]; + while (true) { + int nread = reader.read(buffer, 0, buffer.length); + if (nread < 0) { + break; + } + writer.write(buffer, 0, nread); + writer.close(); + } + } + + public void close() { + if (print != null) { + print.close(); + } + } + } + + public static class Download { + private final MapiSocket server; + private MapiSocket.DownloadStream stream = null; + private String error = null; + + boolean closed = false; + + Download(MapiSocket server) { + this.server = server; + } + + public void sendError(String errorMessage) throws IOException { + if (error != null) { + throw new IOException("another error has already been sent: " + error); + } + error = errorMessage; + } + + public InputStream getStream() throws IOException { + if (error != null) { + throw new IOException("cannot receive data after error has been sent"); + } + if (stream == null) { + stream = server.downloadStream(); + server.getOutputStream().flush(); + } + return stream; + } + public boolean hasBeenUsed() { + return error != null || stream != null; + } + + public String getError() { + return error; + } + public void close() throws IOException { + if (closed) { + return; + } + if (stream != null) { + stream.close(); + } + closed = true; + } + + } }