You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/05/26 14:50:41 UTC

mina-sshd git commit: [SSHD-475] SftpFileChannel should take into account the open mode(s)

Repository: mina-sshd
Updated Branches:
  refs/heads/master 9b60dcc53 -> f80467b7b


[SSHD-475] SftpFileChannel should take into account the open mode(s)


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

Branch: refs/heads/master
Commit: f80467b7be074cd0198df48347def175d08c8bfb
Parents: 9b60dcc
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Tue May 26 15:50:32 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Tue May 26 15:50:32 2015 +0300

----------------------------------------------------------------------
 .../sshd/client/sftp/SftpFileChannel.java       | 60 +++++++++++++++-----
 .../client/sftp/SftpFileSystemProvider.java     | 50 +++++++++-------
 2 files changed, 77 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f80467b7/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileChannel.java
index 3d9244c..ddb8663 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileChannel.java
@@ -33,25 +33,29 @@ import java.nio.channels.WritableByteChannel;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.sshd.client.SftpException;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 
 public class SftpFileChannel extends FileChannel {
 
     private final SftpPath p;
     private final Collection<SftpClient.OpenMode> modes;
     private final SftpClient sftp;
-    private final SftpClient.Handle handle;
+    private final SftpClient.CloseableHandle handle;
     private final Object lock;
     private volatile long pos;
     private volatile Thread blockingThread;
 
     public SftpFileChannel(SftpPath p, Collection<SftpClient.OpenMode> modes) throws IOException {
         this.p = p;
-        this.modes = modes;
+        this.modes = ValidateUtils.checkNotNull(modes, "No channel modes specified", GenericUtils.EMPTY_OBJECT_ARRAY);
         sftp = p.getFileSystem().getClient();
         handle = sftp.open(p.toString(), modes);
         lock = new Object();
@@ -77,8 +81,11 @@ public class SftpFileChannel extends FileChannel {
         return doRead(buffers, -1);
     }
 
+    public static final Set<SftpClient.OpenMode> READ_MODES=
+            Collections.unmodifiableSet(EnumSet.of(SftpClient.OpenMode.Read));
+
     protected long doRead(List<ByteBuffer> buffers, long position) throws IOException {
-        ensureOpen();
+        ensureOpen(READ_MODES);
         synchronized (lock) {
             boolean completed = false;
             boolean eof = false;
@@ -138,8 +145,12 @@ public class SftpFileChannel extends FileChannel {
         return doWrite(buffers, -1);
     }
 
+    public static final Set<SftpClient.OpenMode> WRITE_MODES=
+            Collections.unmodifiableSet(
+                EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Append, SftpClient.OpenMode.Create, SftpClient.OpenMode.Truncate));
+
     protected long doWrite(List<ByteBuffer> buffers, long position) throws IOException {
-        ensureOpen();
+        ensureOpen(WRITE_MODES);
         synchronized (lock) {
             boolean completed = false;
             long curPos = position >= 0 ? position : pos;
@@ -175,7 +186,7 @@ public class SftpFileChannel extends FileChannel {
 
     @Override
     public long position() throws IOException {
-        ensureOpen();
+        ensureOpen(Collections.<SftpClient.OpenMode>emptySet());
         return pos;
     }
 
@@ -184,7 +195,8 @@ public class SftpFileChannel extends FileChannel {
         if (newPosition < 0) {
             throw new IllegalArgumentException("position(" + p + ") illegal file channel position: " + newPosition);
         }
-        ensureOpen();
+
+        ensureOpen(Collections.<SftpClient.OpenMode>emptySet());
         synchronized (lock) {
             pos = newPosition;
             return this;
@@ -193,18 +205,20 @@ public class SftpFileChannel extends FileChannel {
 
     @Override
     public long size() throws IOException {
+        ensureOpen(Collections.<SftpClient.OpenMode>emptySet());
         return sftp.stat(handle).size;
     }
 
     @Override
     public FileChannel truncate(long size) throws IOException {
+        ensureOpen(Collections.<SftpClient.OpenMode>emptySet());
         sftp.setStat(handle, new SftpClient.Attributes().size(size));
         return this;
     }
 
     @Override
     public void force(boolean metaData) throws IOException {
-        // ignored
+        ensureOpen(Collections.<SftpClient.OpenMode>emptySet());
     }
 
     @Override
@@ -212,7 +226,7 @@ public class SftpFileChannel extends FileChannel {
         if ((position < 0) || (count < 0)) {
             throw new IllegalArgumentException("transferTo(" + p + ") illegal position (" + position + ") or count (" + count + ")");
         }
-        ensureOpen();
+        ensureOpen(READ_MODES);
         synchronized (lock) {
             boolean completed = false;
             boolean eof = false;
@@ -249,8 +263,9 @@ public class SftpFileChannel extends FileChannel {
         if ((position < 0) || (count < 0)) {
             throw new IllegalArgumentException("transferFrom(" + p + ") illegal position (" + position + ") or count (" + count + ")");
         }
-        ensureOpen();
-        synchronized (lock) {
+        ensureOpen(WRITE_MODES);
+
+        synchronized(lock) {
             boolean completed = false;
             long curPos = position >= 0 ? position : pos;
             try {
@@ -289,6 +304,8 @@ public class SftpFileChannel extends FileChannel {
 
     @Override
     public FileLock tryLock(final long position, final long size, boolean shared) throws IOException {
+        ensureOpen(Collections.<SftpClient.OpenMode>emptySet());
+
         try {
             sftp.lock(handle, position, size, 0);
         } catch (SftpException e) {
@@ -297,8 +314,8 @@ public class SftpFileChannel extends FileChannel {
             }
             throw e;
         }
-        return new FileLock(this, position, size, shared) {
 
+        return new FileLock(this, position, size, shared) {
             private final AtomicBoolean valid = new AtomicBoolean(true);
 
             @Override
@@ -325,7 +342,7 @@ public class SftpFileChannel extends FileChannel {
             }
         } finally {
             try {
-                sftp.close(handle);
+                handle.close();
             } finally {
                 sftp.close();
             }
@@ -342,10 +359,27 @@ public class SftpFileChannel extends FileChannel {
         end(completed);
     }
 
-    private void ensureOpen() throws IOException {
+    /**
+     * Checks that the channel is open and that its current mode contains
+     * at least one of the required ones
+     * @param reqModes The required modes - ignored if {@code null}/empty
+     * @throws IOException If channel not open or the required modes are not
+     * satisfied
+     */
+    private void ensureOpen(Collection<SftpClient.OpenMode> reqModes) throws IOException {
         if (!isOpen()) {
             throw new ClosedChannelException();
         }
+        
+        if (GenericUtils.size(reqModes) > 0) {
+            for (SftpClient.OpenMode m : reqModes) {
+                if (this.modes.contains(m)) {
+                    return;
+                }
+            }
+            
+            throw new IOException("ensureOpen(" + p + ") current channel modes (" + this.modes + ") do contain any of the required: " + reqModes);
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f80467b7/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
index 6eb2e61..b1f567b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
@@ -185,8 +185,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
 
     @Override
     public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
-        final SftpPath p = toSftpPath(path);
-        final EnumSet<SftpClient.OpenMode> modes = EnumSet.noneOf(SftpClient.OpenMode.class);
+        Collection<SftpClient.OpenMode> modes = EnumSet.noneOf(SftpClient.OpenMode.class);
         for (OpenOption option : options) {
             if (option == StandardOpenOption.READ) {
                 modes.add(SftpClient.OpenMode.Read);
@@ -201,8 +200,16 @@ public class SftpFileSystemProvider extends FileSystemProvider {
             } else if (option == StandardOpenOption.CREATE_NEW) {
                 modes.add(SftpClient.OpenMode.Create);
                 modes.add(SftpClient.OpenMode.Exclusive);
+            } else if (option == StandardOpenOption.SPARSE) {
+                /*
+                 * As per the Javadoc:
+                 * 
+                 *      The option is ignored when the file system does not
+                 *  support the creation of sparse files
+                 */
+                continue;
             } else {
-                throw new IllegalArgumentException("Unsupported open option " + option);
+                throw new IllegalArgumentException("newFileChannel(" + path + ") unsupported open option: " + option);
             }
         }
         if (modes.isEmpty()) {
@@ -210,7 +217,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
             modes.add(SftpClient.OpenMode.Write);
         }
         // TODO: attrs
-        return new SftpFileChannel(p, modes);
+        return new SftpFileChannel(toSftpPath(path), modes);
     }
 
     @Override
@@ -467,26 +474,29 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         SftpPath p = toSftpPath(path);
         boolean w = false;
         boolean x = false;
-        for (AccessMode mode : modes) {
-            switch (mode) {
-                case READ:
-                    break;
-                case WRITE:
-                    w = true;
-                    break;
-                case EXECUTE:
-                    x = true;
-                    break;
-                default:
-                    throw new UnsupportedOperationException("Unsupported mode: " + mode);
+        if (GenericUtils.length(modes) > 0) {
+            for (AccessMode mode : modes) {
+                switch (mode) {
+                    case READ:
+                        break;
+                    case WRITE:
+                        w = true;
+                        break;
+                    case EXECUTE:
+                        x = true;
+                        break;
+                    default:
+                        throw new UnsupportedOperationException("Unsupported mode: " + mode);
+                }
             }
         }
+
         BasicFileAttributes attrs = getFileAttributeView(p, BasicFileAttributeView.class).readAttributes();
-        if (attrs == null && !(p.isAbsolute() && p.getNameCount() == 0)) {
-            throw new NoSuchFileException(toString());
+        if ((attrs == null) && !(p.isAbsolute() && p.getNameCount() == 0)) {
+            throw new NoSuchFileException(path.toString());
         }
-        if (x || w && p.getFileSystem().isReadOnly()) {
-            throw new AccessDeniedException(toString());
+        if (x || (w && p.getFileSystem().isReadOnly())) {
+            throw new AccessDeniedException(path.toString());
         }
     }