Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetConnection.java @ 613:9397c0b487f8
Normalize CRLF on upload
author | Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com> |
---|---|
date | Tue, 18 Jan 2022 13:18:43 +0100 (2022-01-18) |
parents | 6aa38e8c0f2d |
children | 65641a7cea31 |
comparison
equal
deleted
inserted
replaced
612:1d44b8a577ca | 613:9397c0b487f8 |
---|---|
3234 if (uploadHandler == null) { | 3234 if (uploadHandler == null) { |
3235 return "No file upload handler has been registered with the JDBC driver"; | 3235 return "No file upload handler has been registered with the JDBC driver"; |
3236 } | 3236 } |
3237 | 3237 |
3238 final long linesToSkip = offset >= 1 ? offset - 1 : 0; | 3238 final long linesToSkip = offset >= 1 ? offset - 1 : 0; |
3239 final Upload handle = new Upload(server, uploadHandler::uploadCancelled); | 3239 final Upload handle = new Upload(server, uploadHandler::uploadCancelled, textMode); |
3240 final boolean wasFaking = server.setInsertFakePrompts(false); | 3240 final boolean wasFaking = server.setInsertFakePrompts(false); |
3241 try { | 3241 try { |
3242 uploadHandler.handleUpload(handle, path, textMode, linesToSkip); | 3242 uploadHandler.handleUpload(handle, path, textMode, linesToSkip); |
3243 if (!handle.hasBeenUsed()) { | 3243 if (!handle.hasBeenUsed()) { |
3244 throw new IOException("Call to " + uploadHandler.getClass().getCanonicalName() + ".handleUpload for path '" + path + "' sent neither data nor an error message"); | 3244 throw new IOException("Call to " + uploadHandler.getClass().getCanonicalName() + ".handleUpload for path '" + path + "' sent neither data nor an error message"); |
3324 * Handle passed to {@link UploadHandler} to allow communication with the server | 3324 * Handle passed to {@link UploadHandler} to allow communication with the server |
3325 */ | 3325 */ |
3326 public static class Upload { | 3326 public static class Upload { |
3327 private final MapiSocket server; | 3327 private final MapiSocket server; |
3328 private final Runnable cancellationCallback; | 3328 private final Runnable cancellationCallback; |
3329 private final boolean textMode; | |
3329 private PrintStream print = null; | 3330 private PrintStream print = null; |
3330 private String error = null; | 3331 private String error = null; |
3331 private int customChunkSize = -1; | 3332 private int customChunkSize = -1; |
3332 | 3333 |
3333 Upload(MapiSocket server, Runnable cancellationCallback) { | 3334 Upload(MapiSocket server, Runnable cancellationCallback, boolean textMode) { |
3334 this.server = server; | 3335 this.server = server; |
3335 this.cancellationCallback = cancellationCallback; | 3336 this.cancellationCallback = cancellationCallback; |
3337 this.textMode = textMode; | |
3336 } | 3338 } |
3337 | 3339 |
3338 /** | 3340 /** |
3339 * Send an error message to the server | 3341 * Send an error message to the server |
3340 * | 3342 * |
3372 } | 3374 } |
3373 if (print == null) { | 3375 if (print == null) { |
3374 try { | 3376 try { |
3375 final MapiSocket.UploadStream up = customChunkSize >= 0 ? server.uploadStream(customChunkSize) : server.uploadStream(); | 3377 final MapiSocket.UploadStream up = customChunkSize >= 0 ? server.uploadStream(customChunkSize) : server.uploadStream(); |
3376 up.setCancellationCallback(cancellationCallback); | 3378 up.setCancellationCallback(cancellationCallback); |
3377 print = new PrintStream(up, false, "UTF-8"); | 3379 print = new PrintStream(textMode ? new StripCrLfStream(up) : up, false, "UTF-8"); |
3378 up.write('\n'); | 3380 up.write('\n'); |
3379 } catch (UnsupportedEncodingException e) { | 3381 } catch (UnsupportedEncodingException e) { |
3380 throw new RuntimeException("The system is guaranteed to support the UTF-8 encoding but apparently it doesn't", e); | 3382 throw new RuntimeException("The system is guaranteed to support the UTF-8 encoding but apparently it doesn't", e); |
3381 } | 3383 } |
3382 } | 3384 } |
3565 /* ignore close error */ | 3567 /* ignore close error */ |
3566 } | 3568 } |
3567 } | 3569 } |
3568 } | 3570 } |
3569 } | 3571 } |
3572 | |
3573 public static class StripCrLfStream extends FilterOutputStream { | |
3574 private boolean crPending = false; | |
3575 | |
3576 public StripCrLfStream(OutputStream out) { | |
3577 super(out); | |
3578 } | |
3579 | |
3580 public boolean pending() { | |
3581 return this.crPending; | |
3582 } | |
3583 | |
3584 @Override | |
3585 public void write(int b) throws IOException { | |
3586 if (crPending && b != '\n') { | |
3587 out.write('\r'); | |
3588 } | |
3589 if (b != '\r') { | |
3590 out.write(b); | |
3591 crPending = false; | |
3592 } else { | |
3593 crPending = true; | |
3594 } | |
3595 } | |
3596 | |
3597 @Override | |
3598 public void write(byte[] b) throws IOException { | |
3599 this.write(b, 0, b.length); | |
3600 } | |
3601 | |
3602 @Override | |
3603 public void write(byte[] b, int off, int len) throws IOException { | |
3604 if (len == 0) { | |
3605 return; | |
3606 } | |
3607 if (crPending && b[0] != '\n') { | |
3608 out.write('\r'); | |
3609 } | |
3610 | |
3611 // deal with final \r up front | |
3612 if (b[len - 1] == '\r') { | |
3613 crPending = true; | |
3614 len -= 1; | |
3615 } else { | |
3616 crPending = false; | |
3617 } | |
3618 | |
3619 for (int i = off; i < off + len - 1; i++) { | |
3620 if (b[i] == '\r' && b[i + 1] == '\n') { | |
3621 int chunk = i - off; | |
3622 out.write(b, off, chunk); | |
3623 // chunk + 1 because we want to skip the \r | |
3624 len -= chunk + 1; | |
3625 off += chunk + 1; | |
3626 // we don't have to look at the \n because we know it's no \r. | |
3627 i++; | |
3628 } | |
3629 } | |
3630 | |
3631 // write the remainder | |
3632 out.write(b, off, len); | |
3633 } | |
3634 | |
3635 @Override | |
3636 public void flush() throws IOException { | |
3637 // we cannot flush our pending CR but we can ask our downstream to flush what we have sent them so far | |
3638 out.flush(); | |
3639 } | |
3640 | |
3641 @Override | |
3642 public void close() throws IOException { | |
3643 if (crPending) { | |
3644 out.write('\r'); | |
3645 } | |
3646 crPending = false; | |
3647 super.close(); | |
3648 } | |
3649 } | |
3570 } | 3650 } |