comparison src/main/java/org/monetdb/jdbc/MonetConnection.java @ 620:5ab170ddc66a

Some small improvements
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Wed, 19 Jan 2022 21:30:10 +0100 (2022-01-19)
parents 15eb17b911a5
children 1c3cdf0667d7
comparison
equal deleted inserted replaced
619:ffc2fc8e82ec 620:5ab170ddc66a
3142 tmpLine = in.readLine(); 3142 tmpLine = in.readLine();
3143 linetype = in.getLineType(); 3143 linetype = in.getLineType();
3144 break; 3144 break;
3145 case FILETRANSFER: 3145 case FILETRANSFER:
3146 // Consume the command 3146 // Consume the command
3147 String transferCommand = in.readLine(); 3147 final String transferCommand = in.readLine();
3148 // Consume the fake prompt inserted by MapiSocket. 3148 // Consume the fake prompt inserted by MapiSocket.
3149 String dummy = in.readLine(); 3149 in.readLine();
3150 // Handle the request 3150 // Handle the request
3151 if (transferCommand != null) 3151 if (transferCommand != null)
3152 error = handleTransfer(transferCommand); 3152 error = handleTransfer(transferCommand);
3153 else 3153 else
3154 error = "Protocol violation, expected transfer command, got nothing"; 3154 error = "Protocol violation, expected transfer command, got nothing";
3225 } else if (transferCommand.startsWith("rb ")) { 3225 } else if (transferCommand.startsWith("rb ")) {
3226 return handleUpload(transferCommand.substring(3), false, 0); 3226 return handleUpload(transferCommand.substring(3), false, 0);
3227 } else if (transferCommand.startsWith("w ")) { 3227 } else if (transferCommand.startsWith("w ")) {
3228 return handleDownload(transferCommand.substring(2), true); 3228 return handleDownload(transferCommand.substring(2), true);
3229 } else if (transferCommand.startsWith("wb ")) { 3229 } else if (transferCommand.startsWith("wb ")) {
3230 return handleDownload(transferCommand.substring(2), false); 3230 return handleDownload(transferCommand.substring(3), false);
3231 } 3231 }
3232 return "JDBC does not support this file transfer yet: " + transferCommand; 3232 return "JDBC does not support this file transfer yet: " + transferCommand;
3233 } 3233 }
3234 3234
3235 private String handleUpload(final String path, final boolean textMode, final long offset) throws IOException { 3235 private String handleUpload(final String path, final boolean textMode, final long offset) throws IOException {
3243 try { 3243 try {
3244 uploadHandler.handleUpload(handle, path, textMode, linesToSkip); 3244 uploadHandler.handleUpload(handle, path, textMode, linesToSkip);
3245 if (!handle.hasBeenUsed()) { 3245 if (!handle.hasBeenUsed()) {
3246 throw new IOException("Call to " + uploadHandler.getClass().getCanonicalName() + ".handleUpload for path '" + path + "' sent neither data nor an error message"); 3246 throw new IOException("Call to " + uploadHandler.getClass().getCanonicalName() + ".handleUpload for path '" + path + "' sent neither data nor an error message");
3247 } 3247 }
3248 } finally {
3248 handle.close(); 3249 handle.close();
3249 } finally {
3250 server.setInsertFakePrompts(wasFaking); 3250 server.setInsertFakePrompts(wasFaking);
3251 } 3251 }
3252 return handle.getError(); 3252 return handle.getError();
3253 } 3253 }
3254 3254
3255 private String handleDownload(final String path, boolean textMode) throws IOException { 3255 private String handleDownload(final String path, final boolean textMode) throws IOException {
3256 if (downloadHandler == null) { 3256 if (downloadHandler == null) {
3257 return "No file download handler has been registered with the JDBC driver"; 3257 return "No file download handler has been registered with the JDBC driver";
3258 } 3258 }
3259 3259
3260 final Download handle = new Download(server, textMode); 3260 final Download handle = new Download(server, textMode);
3280 public interface UploadHandler { 3280 public interface UploadHandler {
3281 /** 3281 /**
3282 * Called if the server sends a request to read file data. 3282 * Called if the server sends a request to read file data.
3283 * 3283 *
3284 * Use the given handle to receive data or send errors to the server. 3284 * Use the given handle to receive data or send errors to the server.
3285 * @param handle Handle to communicate with the server 3285 *
3286 * @param handle Handle to communicate with the server
3286 * @param name Name of the file the server would like to read. Make sure 3287 * @param name Name of the file the server would like to read. Make sure
3287 * to validate this before reading from the file system 3288 * to validate this before reading from the file system
3288 * @param textMode Whether to open the file as text or binary data. 3289 * @param textMode Whether to open the file as text or binary data.
3289 * @param linesToSkip In text mode, number of initial lines to skip. 3290 * @param linesToSkip In text mode, number of initial lines to skip.
3290 * 0 means upload everything, 1 means skip the first line, etc. 3291 * 0 means upload everything, 1 means skip the first line, etc.
3313 * Called if the server sends a request to write a file. 3314 * Called if the server sends a request to write a file.
3314 * 3315 *
3315 * Use the given handle to send data or errors to the server. 3316 * Use the given handle to send data or errors to the server.
3316 * 3317 *
3317 * @param handle Handle to communicate with the server 3318 * @param handle Handle to communicate with the server
3318 * @param name Name of the file the server would like to write. Make sure to validate this before writing to 3319 * @param name Name of the file the server would like to write. Make sure
3319 * the file system 3320 * to validate this before writing to the file system
3320 * @param textMode Whether this is text or binary data. 3321 * @param textMode Whether this is text or binary data.
3321 */ 3322 */
3322 void handleDownload(Download handle, String name, boolean textMode) throws IOException; 3323 void handleDownload(Download handle, String name, boolean textMode) throws IOException;
3323 } 3324 }
3324 3325
3420 3421
3421 /** 3422 /**
3422 * Read data from the given buffered reader and send it to the server 3423 * Read data from the given buffered reader and send it to the server
3423 * @param reader reader to read from 3424 * @param reader reader to read from
3424 * @param linesToSkip start uploading at line {@code offset}. Value 0 and 1 3425 * @param linesToSkip start uploading at line {@code offset}. Value 0 and 1
3425 * both mean upload the whole file, value 2 means skip the first line, etc.q 3426 * both mean upload the whole file, value 2 means skip the first line, etc.
3426 */ 3427 */
3427 public void uploadFrom(final BufferedReader reader, final long linesToSkip) throws IOException { 3428 public void uploadFrom(final BufferedReader reader, final long linesToSkip) throws IOException {
3428 for (int i = 0; i < linesToSkip; i++) { 3429 for (int i = 0; i < linesToSkip; i++) {
3429 String line = reader.readLine(); 3430 String line = reader.readLine();
3430 if (line == null) { 3431 if (line == null) {
3492 * {@link IOException} but this will terminate the connection. 3493 * {@link IOException} but this will terminate the connection.
3493 * 3494 *
3494 * Note: as of MonetDB version Jul2021 the server always terminates the connection 3495 * Note: as of MonetDB version Jul2021 the server always terminates the connection
3495 * when this error is used. This will probably change in the future. 3496 * when this error is used. This will probably change in the future.
3496 */ 3497 */
3497 public void sendError(String errorMessage) throws IOException { 3498 public void sendError(final String errorMessage) throws IOException {
3498 if (error != null) { 3499 if (error != null) {
3499 throw new IOException("another error has already been sent: " + error); 3500 throw new IOException("another error has already been sent: " + error);
3500 } 3501 }
3501 error = errorMessage; 3502 error = errorMessage;
3502 } 3503 }
3542 final InputStream s = getStream(); 3543 final InputStream s = getStream();
3543 final InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8); 3544 final InputStreamReader r = new InputStreamReader(s, StandardCharsets.UTF_8);
3544 final char[] buffer = new char[65536]; 3545 final char[] buffer = new char[65536];
3545 while (true) { 3546 while (true) {
3546 final int nread = r.read(buffer); 3547 final int nread = r.read(buffer);
3547 if (nread < 0) 3548 if (nread < 0) {
3548 break; 3549 break;
3550 }
3549 writer.write(buffer, 0, nread); 3551 writer.write(buffer, 0, nread);
3550 } 3552 }
3551 } 3553 }
3552 3554
3553 /** 3555 /**
3554 * @return true if data has been received or an error has been sent. 3556 * @return true if data has been received or an error has been sent.
3555 */ 3557 */
3556 public boolean hasBeenUsed() { 3558 public boolean hasBeenUsed() {
3557 return error != null || stream != null; 3559 return stream != null || error != null;
3558 } 3560 }
3559 3561
3560 /** 3562 /**
3561 * @return the error that was sent, if any 3563 * @return the error that was sent, if any
3562 */ 3564 */
3581 /** 3583 /**
3582 * Set the line endings used in the stream returned by {@link Download#getStream()} 3584 * Set the line endings used in the stream returned by {@link Download#getStream()}
3583 * @param sep separator to use 3585 * @param sep separator to use
3584 * @throws IllegalArgumentException if sep is neither "\n" nor "\r\n" 3586 * @throws IllegalArgumentException if sep is neither "\n" nor "\r\n"
3585 */ 3587 */
3586 public void setLineSeparator(String sep) { 3588 public void setLineSeparator(final String sep) {
3587 if ("\n".equals(sep)) { 3589 if ("\n".equals(sep)) {
3588 prependCr = false; 3590 prependCr = false;
3589 } else if ("\r\n".equals(sep)) { 3591 } else if ("\r\n".equals(sep)) {
3590 prependCr = true; 3592 prependCr = true;
3591 } else { 3593 } else {
3592 throw new IllegalArgumentException("sep must be \n or \r\n"); 3594 throw new IllegalArgumentException("sep must be \\n or \\r\\n");
3593 } 3595 }
3594 } 3596 }
3595 } 3597 }
3596 3598
3597 public static class StripCrLfStream extends FilterOutputStream { 3599 public static class StripCrLfStream extends FilterOutputStream {
3604 public boolean pending() { 3606 public boolean pending() {
3605 return this.crPending; 3607 return this.crPending;
3606 } 3608 }
3607 3609
3608 @Override 3610 @Override
3609 public void write(int b) throws IOException { 3611 public void write(final int b) throws IOException {
3610 if (crPending && b != '\n') { 3612 if (crPending && b != '\n') {
3611 out.write('\r'); 3613 out.write('\r');
3612 } 3614 }
3613 if (b != '\r') { 3615 if (b != '\r') {
3614 out.write(b); 3616 out.write(b);
3615 crPending = false; 3617 crPending = false;
3616 } else { 3618 } else {
3617 crPending = true; 3619 crPending = true;
3618 } 3620 }
3619 } 3621 }
3620 3622
3621 @Override 3623 @Override
3622 public void write(byte[] b) throws IOException { 3624 public void write(final byte[] b) throws IOException {
3623 this.write(b, 0, b.length); 3625 this.write(b, 0, b.length);
3624 } 3626 }
3625 3627
3626 @Override 3628 @Override
3627 public void write(byte[] b, int off, int len) throws IOException { 3629 public void write(final byte[] b, int off, int len) throws IOException {
3628 if (len == 0) { 3630 if (len == 0) {
3629 return; 3631 return;
3630 } 3632 }
3631 if (crPending && b[0] != '\n') { 3633 if (crPending && b[0] != '\n') {
3632 out.write('\r'); 3634 out.write('\r');