Repository: mina-sshd
Updated Branches:
  refs/heads/master 3b1342efc -> d5ce26836


[SSHD-697] Added support for reset and skip for SftpInputStreamWithChannel


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/d5ce2683
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/d5ce2683
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/d5ce2683

Branch: refs/heads/master
Commit: d5ce26836fac879ab55915f0cf9096fa978fd02f
Parents: 3b1342e
Author: Goldstein Lyor <[email protected]>
Authored: Thu Sep 29 16:42:45 2016 +0300
Committer: Goldstein Lyor <[email protected]>
Committed: Thu Sep 29 16:42:45 2016 +0300

----------------------------------------------------------------------
 .../sftp/SftpInputStreamWithChannel.java        | 51 +++++++++++++++++++
 .../sshd/server/subsystem/sftp/FileHandle.java  | 29 +++++------
 .../sshd/client/subsystem/sftp/SftpTest.java    | 53 ++++++++++++++++++++
 3 files changed, 119 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d5ce2683/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
index adf2cc5..af208ad 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpInputStreamWithChannel.java
@@ -73,6 +73,57 @@ public class SftpInputStreamWithChannel extends 
InputStreamWithChannel {
     }
 
     @Override
+    public boolean markSupported() {
+        return false;
+    }
+
+    @Override
+    public synchronized void mark(int readlimit) {
+        throw new UnsupportedOperationException("mark(" + readlimit + ") N/A");
+    }
+
+    @Override
+    public long skip(long n) throws IOException {
+        long skipLen;
+        long newIndex = index + n;
+        long bufLen = Math.max(0L, available);
+        if (newIndex > bufLen) {
+            // exceeded current buffer
+            long extraLen = newIndex - bufLen;
+            offset += extraLen;
+            skipLen = Math.max(0, bufLen - index) + extraLen;
+            // force re-fill of read buffer
+            index = 0;
+            available = 0;
+        } else if (newIndex < 0) {
+            // went back - check how far back
+            long startOffset = offset - bufLen;
+            long newOffset = startOffset + newIndex; // actually a subtraction 
since newIndex is negative
+            newOffset = Math.max(0L, newOffset);
+            skipLen = index - newIndex; // actually a adding it since newIndex 
is negative
+            offset = newOffset;
+            // force re-fill of read buffer
+            index = 0;
+            available = 0;
+        } else {
+            // still within current buffer
+            index = (int) newIndex;
+            // need to use absolute value since skip size may have been 
negative
+            skipLen = Math.abs(n);
+        }
+
+        return skipLen;
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        offset = 0L;
+        // force re-fill of read buffer
+        index = 0;
+        available = 0;
+    }
+
+    @Override
     public int read() throws IOException {
         int read = read(bb, 0, 1);
         if (read > 0) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d5ce2683/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java 
b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
index e27fddd..075665a 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
@@ -47,7 +47,6 @@ public class FileHandle extends Handle {
 
     private final int access;
     private final FileChannel fileChannel;
-    private long pos;
     private final List<FileLock> locks = new ArrayList<>();
 
     public FileHandle(SftpSubsystem sftpSubsystem, Path file, int flags, int 
access, Map<String, Object> attrs) throws IOException {
@@ -108,7 +107,6 @@ public class FileHandle extends Handle {
             sftpSubsystem.doSetAttributes(file, attrs);
         }
         this.fileChannel = channel;
-        this.pos = 0;
     }
 
     public final FileChannel getFileChannel() {
@@ -129,13 +127,21 @@ public class FileHandle extends Handle {
 
     public int read(byte[] data, int doff, int length, long offset) throws 
IOException {
         FileChannel channel = getFileChannel();
-        if (pos != offset) {
-            channel.position(offset);
-            pos = offset;
+        channel.position(offset);
+
+        long size = channel.size();
+        long curPos = channel.position();
+        long available = size - curPos;
+        if (available <= 0) {
+            return -1;
+        }
+
+        int bufLen = length;
+        if (bufLen > available) {
+            bufLen = (int) available;   // debug breakpoint
         }
-        int read = channel.read(ByteBuffer.wrap(data, doff, length));
-        pos += read;
-        return read;
+
+        return channel.read(ByteBuffer.wrap(data, doff, bufLen));
     }
 
     public void append(byte[] data) throws IOException {
@@ -153,13 +159,8 @@ public class FileHandle extends Handle {
 
     public void write(byte[] data, int doff, int length, long offset) throws 
IOException {
         FileChannel channel = getFileChannel();
-        if (pos != offset) {
-            channel.position(offset);
-            pos = offset;
-        }
-
+        channel.position(offset);
         channel.write(ByteBuffer.wrap(data, doff, length));
-        pos += length;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/d5ce2683/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java 
b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index 58ae35d..d2633d3 100644
--- 
a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ 
b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -463,6 +463,59 @@ public class SftpTest extends 
AbstractSftpClientTestSupport {
     }
 
     @Test
+    public void testInputStreamSkipAndReset() throws Exception {
+        Path targetPath = detectTargetFolder();
+        Path parentPath = targetPath.getParent();
+        Path localFile = Utils.resolve(targetPath, 
SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), 
getCurrentTestName());
+        Files.createDirectories(localFile.getParent());
+        byte[] data = (getClass().getName() + "#" + getCurrentTestName() + "[" 
+ localFile + "]").getBytes(StandardCharsets.UTF_8);
+        Files.write(localFile, data, StandardOpenOption.CREATE);
+        try (ClientSession session = client.connect(getCurrentTestName(), 
TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) {
+            session.addPasswordIdentity(getCurrentTestName());
+            session.auth().verify(5L, TimeUnit.SECONDS);
+
+            try (SftpClient sftp = session.createSftpClient();
+                 InputStream stream = 
sftp.read(Utils.resolveRelativeRemotePath(parentPath, localFile), 
OpenMode.Read)) {
+                assertFalse("Stream reported mark supported", 
stream.markSupported());
+                try {
+                    stream.mark(data.length);
+                    fail("Unexpected success to mark the read limit");
+                } catch (UnsupportedOperationException e) {
+                    // expected - ignored
+                }
+
+                byte[] expected = new byte[data.length / 4];
+                int readLen = stream.read(expected);
+                assertEquals("Failed to read fully initial data", 
expected.length, readLen);
+
+                byte[] actual = new byte[readLen];
+                stream.reset();
+                readLen = stream.read(actual);
+                assertEquals("Failed to read fully reset data", actual.length, 
readLen);
+                assertArrayEquals("Mismatched re-read data contents", 
expected, actual);
+
+                System.arraycopy(data, 0, expected, 0, expected.length);
+                assertArrayEquals("Mismatched original data contents", 
expected, actual);
+
+                long skipped = stream.skip(readLen);
+                assertEquals("Mismatched skipped forward size", readLen, 
skipped);
+
+                readLen = stream.read(actual);
+                assertEquals("Failed to read fully skipped forward data", 
actual.length, readLen);
+
+                System.arraycopy(data, expected.length + readLen, expected, 0, 
expected.length);
+                assertArrayEquals("Mismatched skipped forward data contents", 
expected, actual);
+
+                skipped = stream.skip(0 - readLen);
+                assertEquals("Mismatched backward skip size", readLen, 
skipped);
+                readLen = stream.read(actual);
+                assertEquals("Failed to read fully skipped backward data", 
actual.length, readLen);
+                assertArrayEquals("Mismatched skipped backward data contents", 
expected, actual);
+            }
+        }
+    }
+
+    @Test
     @SuppressWarnings({"checkstyle:anoninnerlength", 
"checkstyle:methodlength"})
     public void testClient() throws Exception {
         List<NamedFactory<Command>> factories = sshd.getSubsystemFactories();

Reply via email to