You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2012/07/16 16:10:40 UTC
svn commit: r1362045 - in /commons/proper/vfs/trunk: ./
core/src/main/java/org/apache/commons/vfs2/
core/src/main/java/org/apache/commons/vfs2/cache/
core/src/main/java/org/apache/commons/vfs2/impl/
core/src/main/java/org/apache/commons/vfs2/provider/ ...
Author: ggregory
Date: Mon Jul 16 14:10:39 2012
New Revision: 1362045
URL: http://svn.apache.org/viewvc?rev=1362045&view=rev
Log:
[VFS-405] Get/set the file permissions.
[VFS-415] Update VFS requirement to Java 1.6.
Added:
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java (with props)
commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java (with props)
Removed:
commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/local/test/PermissionsTests.java
Modified:
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/FileObject.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/Resources.properties
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/local/LocalFile.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java
commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java
commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/local/test/LocalProviderTestCase.java
commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
commons/proper/vfs/trunk/pom.xml
commons/proper/vfs/trunk/src/changes/changes.xml
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/FileObject.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/FileObject.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/FileObject.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/FileObject.java Mon Jul 16 14:10:39 2012
@@ -193,6 +193,48 @@ public interface FileObject extends Comp
throws FileSystemException;
/**
+ * Sets the owner's (or everybody's) write permission
+ *
+ * @param executable
+ * True to allow read access, false to disallow
+ * @param ownerOnly
+ * If <code>true</code>, the permission applies only to the owner; otherwise, it applies to everybody.
+ * @return true if the operation succeeded
+ * @throws FileSystemException
+ * On error determining if this file exists.
+ * @since 2.1
+ */
+ boolean setExecutable(boolean executable, boolean ownerOnly) throws FileSystemException;
+
+ /**
+ * Sets the owner's (or everybody's) read permission
+ *
+ * @param readable
+ * True to allow read access, false to disallow
+ * @param ownerOnly
+ * If <code>true</code>, the permission applies only to the owner; otherwise, it applies to everybody.
+ * @return true if the operation succeeded
+ * @throws FileSystemException
+ * On error determining if this file exists.
+ * @since 2.1
+ */
+ boolean setReadable(boolean readable, boolean ownerOnly) throws FileSystemException;
+
+ /**
+ * Sets the owner's (or everybody's) write permission
+ *
+ * @param writable
+ * True to allow read access, false to disallow
+ * @param ownerOnly
+ * If <code>true</code>, the permission applies only to the owner; otherwise, it applies to everybody.
+ * @return true if the operation succeeded
+ * @throws FileSystemException
+ * On error determining if this file exists.
+ * @since 2.1
+ */
+ boolean setWritable(boolean writable, boolean ownerOnly) throws FileSystemException;
+
+ /**
* Finds a file, relative to this file. Equivalent to calling
* <code>resolveFile( path, NameScope.FILE_SYSTEM )</code>.
*
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/Resources.properties
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/Resources.properties?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/Resources.properties (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/Resources.properties Mon Jul 16 14:10:39 2012
@@ -57,6 +57,9 @@ vfs.provider/check-is-executable.error=C
vfs.provider/check-is-hidden.error=Could not determine if file "{0}" is hidden.
vfs.provider/check-is-writeable.error=Could not determine if file "{0}" is writeable.
vfs.provider/check-is-readable.error=Could not determine if file "{0}" is readable.
+vfs.provider/set-executable.error=Could not set the executable flag of file "{0}".
+vfs.provider/set-writeable.error=Could not set the writeable flag of file "{0}".
+vfs.provider/set-readable.error=Could not set the readable flag of file "{0}".
vfs.provider/get-url.error=Could not create URL for "{0}".
vfs.provider/resync.error=Could not resync "{0}".
vfs.provider/close.error=Could not close "{0}".
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java Mon Jul 16 14:10:39 2012
@@ -157,6 +157,27 @@ public class OnCallRefreshFileObject ext
}
@Override
+ public boolean setExecutable(boolean executable, boolean ownerOnly) throws FileSystemException
+ {
+ refresh();
+ return super.setExecutable(executable, ownerOnly);
+ }
+
+ @Override
+ public boolean setReadable(boolean readable, boolean ownerOnly) throws FileSystemException
+ {
+ refresh();
+ return super.setReadable(readable, ownerOnly);
+ }
+
+ @Override
+ public boolean setWritable(boolean writable, boolean ownerOnly) throws FileSystemException
+ {
+ refresh();
+ return super.setWritable(writable, ownerOnly);
+ }
+
+ @Override
public void moveTo(FileObject destFile) throws FileSystemException
{
refresh();
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java Mon Jul 16 14:10:39 2012
@@ -159,11 +159,29 @@ public class DecoratedFileObject impleme
return decoratedFileObject.isReadable();
}
+ @Override
+ public boolean setReadable(boolean readable, boolean ownerOnly) throws FileSystemException
+ {
+ return decoratedFileObject.setReadable(readable, ownerOnly);
+ }
+
public boolean isWriteable() throws FileSystemException
{
return decoratedFileObject.isWriteable();
}
+ @Override
+ public boolean setWritable(boolean writable, boolean ownerOnly) throws FileSystemException
+ {
+ return decoratedFileObject.setWritable(writable, ownerOnly);
+ }
+
+ @Override
+ public boolean setExecutable(boolean executable, boolean ownerOnly) throws FileSystemException
+ {
+ return decoratedFileObject.setExecutable(executable, ownerOnly);
+ }
+
public Iterator<FileObject> iterator()
{
return decoratedFileObject.iterator();
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java Mon Jul 16 14:10:39 2012
@@ -181,6 +181,38 @@ public class SynchronizedFileObject exte
}
@Override
+ public boolean isExecutable() throws FileSystemException
+ {
+ synchronized (this) {
+ return super.isExecutable();
+ }
+ }
+
+ @Override
+ public boolean setReadable(boolean readable, boolean ownerOnly) throws FileSystemException
+ {
+ synchronized (this) {
+ return super.setReadable(readable, ownerOnly);
+ }
+ }
+
+ @Override
+ public boolean setWritable(boolean writable, boolean ownerOnly) throws FileSystemException
+ {
+ synchronized (this) {
+ return super.setWritable(writable, ownerOnly);
+ }
+ }
+
+ @Override
+ public boolean setExecutable(boolean executable, boolean ownerOnly) throws FileSystemException
+ {
+ synchronized (this) {
+ return super.setExecutable(executable, ownerOnly);
+ }
+ }
+
+ @Override
public void moveTo(FileObject destFile) throws FileSystemException
{
synchronized (this)
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/AbstractFileObject.java Mon Jul 16 14:10:39 2012
@@ -176,6 +176,17 @@ public abstract class AbstractFileObject
}
/**
+ * Only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+ *
+ * @see {@link #setReadable(boolean, boolean)}
+ * @since 2.1
+ */
+ protected boolean doSetReadable(boolean readable, boolean ownerOnly) throws Exception
+ {
+ return false;
+ }
+
+ /**
* Determines if this file can be written to. Is only called if
* {@link #doGetType} does not return {@link FileType#IMAGINARY}.
* <p/>
@@ -189,6 +200,28 @@ public abstract class AbstractFileObject
}
/**
+ * Only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+ *
+ * @see {@link #setWritable(boolean, boolean)}
+ * @since 2.1
+ */
+ protected boolean doSetWritable(boolean writable, boolean ownerOnly) throws Exception
+ {
+ return false;
+ }
+
+ /**
+ * Only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+ *
+ * @see {@link #setExecutable(boolean, boolean)}
+ * @since 2.1
+ */
+ protected boolean doSetExecutable(boolean writable, boolean ownerOnly) throws Exception
+ {
+ return false;
+ }
+
+ /**
* Lists the children of this file. Is only called if {@link #doGetType}
* returns {@link FileType#FOLDER}. The return value of this method
* is cached, so the implementation can be expensive.<br />
@@ -620,6 +653,26 @@ public abstract class AbstractFileObject
}
}
+ @Override
+ public boolean setReadable(boolean readable, boolean ownerOnly) throws FileSystemException
+ {
+ try
+ {
+ if (exists())
+ {
+ return doSetReadable(readable, ownerOnly);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (final Exception exc)
+ {
+ throw new FileSystemException("vfs.provider/set-readable.error", name, exc);
+ }
+ }
+
/**
* Determines if this file can be written to.
* @return true if the file can be written to, false otherwise.
@@ -649,6 +702,46 @@ public abstract class AbstractFileObject
}
}
+ @Override
+ public boolean setWritable(boolean readable, boolean ownerOnly) throws FileSystemException
+ {
+ try
+ {
+ if (exists())
+ {
+ return doSetWritable(readable, ownerOnly);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (final Exception exc)
+ {
+ throw new FileSystemException("vfs.provider/set-writeable.error", name, exc);
+ }
+ }
+
+ @Override
+ public boolean setExecutable(boolean readable, boolean ownerOnly) throws FileSystemException
+ {
+ try
+ {
+ if (exists())
+ {
+ return doSetExecutable(readable, ownerOnly);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (final Exception exc)
+ {
+ throw new FileSystemException("vfs.provider/set-executable.error", name, exc);
+ }
+ }
+
/**
* Returns an iterator over a set of all FileObject in this file object.
*
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/local/LocalFile.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/local/LocalFile.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/local/LocalFile.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/local/LocalFile.java Mon Jul 16 14:10:39 2012
@@ -161,6 +161,12 @@ public class LocalFile extends AbstractF
return file.canWrite();
}
+ @Override
+ protected boolean doSetWritable(boolean writable, boolean ownerOnly) throws Exception
+ {
+ return file.setWritable(writable, ownerOnly);
+ }
+
/**
* Determines if this file is hidden.
*/
@@ -188,6 +194,18 @@ public class LocalFile extends AbstractF
return file.canRead();
}
+ @Override
+ protected boolean doSetReadable(boolean readable, boolean ownerOnly) throws Exception
+ {
+ return file.setReadable(readable, ownerOnly);
+ }
+
+ @Override
+ protected boolean doSetExecutable(boolean executable, boolean ownerOnly) throws Exception
+ {
+ return file.setExecutable(executable, ownerOnly);
+ }
+
/**
* Gets the last modified time of this file.
*/
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileObject.java Mon Jul 16 14:10:39 2012
@@ -20,9 +20,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.Vector;
+import com.jcraft.jsch.JSchException;
import org.apache.commons.vfs2.FileNotFoundException;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
@@ -33,10 +35,7 @@ import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileObject;
import org.apache.commons.vfs2.provider.UriParser;
-import org.apache.commons.vfs2.util.FileObjectUtils;
-import org.apache.commons.vfs2.util.MonitorInputStream;
-import org.apache.commons.vfs2.util.MonitorOutputStream;
-import org.apache.commons.vfs2.util.RandomAccessMode;
+import org.apache.commons.vfs2.util.*;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
@@ -240,19 +239,23 @@ public class SftpFileObject extends Abst
@Override
protected boolean doSetLastModifiedTime(final long modtime) throws Exception
{
+ int newMTime = (int) (modtime / MOD_TIME_FACTOR);
+ attrs.setACMODTIME(attrs.getATime(), newMTime);
+ flushStat();
+ return true;
+ }
+
+ private void flushStat() throws IOException, SftpException
+ {
final ChannelSftp channel = fileSystem.getChannel();
try
{
- int newMTime = (int) (modtime / MOD_TIME_FACTOR);
-
- attrs.setACMODTIME(attrs.getATime(), newMTime);
channel.setStat(relPath, attrs);
}
finally
{
fileSystem.putChannel(channel);
}
- return true;
}
/**
@@ -298,6 +301,103 @@ public class SftpFileObject extends Abst
}
/**
+ * Returns the POSIX type permissions of the file.
+ *
+ * @boolean true if user and group ID should be checked (needed for some access rights checks)
+ * @return A PosixPermission object
+ * @throws Exception If an error occurs
+ * @since 2.1
+ */
+ protected PosixPermissions getPermissions(boolean checkIds) throws Exception
+ {
+ statSelf();
+ boolean isInGroup = false;
+ if (checkIds)
+ {
+ for (int groupId : fileSystem.getGroupsIds())
+ {
+ if (groupId == attrs.getGId())
+ {
+ isInGroup = true;
+ break;
+ }
+ }
+ }
+ final boolean isOwner = checkIds ? attrs.getUId() == fileSystem.getUId() : false;
+ final PosixPermissions permissions = new PosixPermissions(attrs.getPermissions(), isOwner, isInGroup);
+
+ return permissions;
+ }
+
+ @Override
+ protected boolean doIsReadable() throws Exception
+ {
+ return getPermissions(true).isReadable();
+ }
+
+ @Override
+ protected boolean doSetReadable(boolean readable, boolean ownerOnly) throws Exception
+ {
+ final PosixPermissions permissions = getPermissions(false);
+ int newPermissions = permissions.makeReadable(readable, ownerOnly);
+ if (newPermissions == permissions.getPermissions())
+ {
+ return true;
+ }
+
+ attrs.setPERMISSIONS(newPermissions);
+ flushStat();
+
+ return true;
+ }
+
+ @Override
+ protected boolean doIsWriteable() throws Exception
+ {
+ return getPermissions(true).isWritable();
+ }
+
+ @Override
+ protected boolean doSetWritable(boolean writable, boolean ownerOnly) throws Exception
+ {
+ final PosixPermissions permissions = getPermissions(false);
+ int newPermissions = permissions.makeWritable(writable, ownerOnly);
+ if (newPermissions == permissions.getPermissions())
+ {
+ return true;
+ }
+
+ attrs.setPERMISSIONS(newPermissions);
+ flushStat();
+
+ return true;
+ }
+
+ @Override
+ protected boolean doIsExecutable() throws Exception
+ {
+ final PosixPermissions permissions = getPermissions(true);
+ return permissions.isExecutable();
+ }
+
+
+ @Override
+ protected boolean doSetExecutable(boolean executable, boolean ownerOnly) throws Exception
+ {
+ final PosixPermissions permissions = getPermissions(false);
+ int newPermissions = permissions.makeExecutable(executable, ownerOnly);
+ if (newPermissions == permissions.getPermissions())
+ {
+ return true;
+ }
+
+ attrs.setPERMISSIONS(newPermissions);
+ flushStat();
+
+ return true;
+ }
+
+ /**
* Lists the children of this file.
*/
@Override
Modified: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java (original)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java Mon Jul 16 14:10:39 2012
@@ -17,8 +17,11 @@
package org.apache.commons.vfs2.provider.sftp;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
import java.util.Collection;
+import com.jcraft.jsch.*;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
@@ -30,11 +33,6 @@ import org.apache.commons.vfs2.provider.
import org.apache.commons.vfs2.provider.GenericFileName;
import org.apache.commons.vfs2.util.UserAuthenticatorUtils;
-import com.jcraft.jsch.ChannelSftp;
-import com.jcraft.jsch.JSchException;
-import com.jcraft.jsch.Session;
-import com.jcraft.jsch.SftpException;
-
/**
* Represents the files on an SFTP server.
*/
@@ -48,6 +46,14 @@ public class SftpFileSystem
private Session session;
// private final JSch jSch;
private ChannelSftp idleChannel;
+ /**
+ * Cache for the user ID (-1 when not set)
+ */
+ private int uid = -1;
+ /**
+ * Cache for the user groups ids (null when not set)
+ */
+ private int[] groupsIds;
protected SftpFileSystem(final GenericFileName rootName,
final Session session,
@@ -78,42 +84,7 @@ public class SftpFileSystem
*/
protected ChannelSftp getChannel() throws IOException
{
- if (this.session == null || !this.session.isConnected())
- {
- doCloseCommunicationLink();
-
- // channel closed. e.g. by freeUnusedResources, but now we need it again
- Session session;
- UserAuthenticationData authData = null;
- try
- {
- final GenericFileName rootName = (GenericFileName) getRootName();
-
- authData = UserAuthenticatorUtils.authenticate(getFileSystemOptions(),
- SftpFileProvider.AUTHENTICATOR_TYPES);
-
- session = SftpClientFactory.createConnection(
- rootName.getHostName(),
- rootName.getPort(),
- UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME,
- UserAuthenticatorUtils.toChar(rootName.getUserName())),
- UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD,
- UserAuthenticatorUtils.toChar(rootName.getPassword())),
- getFileSystemOptions());
- }
- catch (final Exception e)
- {
- throw new FileSystemException("vfs.provider.sftp/connect.error",
- getRootName(),
- e);
- }
- finally
- {
- UserAuthenticatorUtils.cleanup(authData);
- }
-
- this.session = session;
- }
+ ensureSession();
try
{
@@ -157,6 +128,49 @@ public class SftpFileSystem
}
/**
+ * Ensures that the session link is established
+ */
+ private void ensureSession() throws FileSystemException
+ {
+ if (this.session == null || !this.session.isConnected())
+ {
+ doCloseCommunicationLink();
+
+ // channel closed. e.g. by freeUnusedResources, but now we need it again
+ Session session;
+ UserAuthenticationData authData = null;
+ try
+ {
+ final GenericFileName rootName = (GenericFileName) getRootName();
+
+ authData = UserAuthenticatorUtils.authenticate(getFileSystemOptions(),
+ SftpFileProvider.AUTHENTICATOR_TYPES);
+
+ session = SftpClientFactory.createConnection(
+ rootName.getHostName(),
+ rootName.getPort(),
+ UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME,
+ UserAuthenticatorUtils.toChar(rootName.getUserName())),
+ UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD,
+ UserAuthenticatorUtils.toChar(rootName.getPassword())),
+ getFileSystemOptions());
+ }
+ catch (final Exception e)
+ {
+ throw new FileSystemException("vfs.provider.sftp/connect.error",
+ getRootName(),
+ e);
+ }
+ finally
+ {
+ UserAuthenticatorUtils.cleanup(authData);
+ }
+
+ this.session = session;
+ }
+ }
+
+ /**
* Returns a channel to the pool.
*/
protected void putChannel(final ChannelSftp channel)
@@ -205,4 +219,90 @@ public class SftpFileSystem
{
return LAST_MOD_TIME_ACCURACY;
}
+
+ /**
+ * Get the (numeric) group ids
+ * @return
+ * @throws JSchException If a problem occurs while retrieving the groups ID
+ */
+ public int[] getGroupsIds() throws JSchException, IOException
+ {
+ if (groupsIds == null)
+ {
+
+ StringBuilder output = new StringBuilder();
+ int code = executeCommand("id -G", output);
+ if (code != 0)
+ throw new JSchException("Could not get the groups id of the current user (error code: " + code + ")");
+
+ // Retrieve the different groups
+ final String[] groups = output.toString().trim().split("\\s+");
+
+ int [] groupsIds = new int [groups.length];
+ for(int i = 0; i < groups.length; i++)
+ groupsIds[i] = Integer.parseInt(groups[i]);
+
+ this.groupsIds = groupsIds;
+
+ }
+ return groupsIds;
+ }
+
+ /**
+ * Get the (numeric) group ids
+ * @return The numeric user ID
+ * @throws JSchException
+ * @throws IOException
+ */
+ public int getUId() throws JSchException, IOException
+ {
+ if (uid < 0)
+ {
+
+ StringBuilder output = new StringBuilder();
+ int code = executeCommand("id -u", output);
+ if (code != 0)
+ throw new JSchException("Could not get the user id of the current user (error code: " + code + ")");
+ uid = Integer.parseInt(output.toString().trim());
+ }
+ return uid;
+ }
+
+ /**
+ * Execute a command and returns the (standard) output through a StringBuilder
+ * @param command The command
+ * @param output The output
+ * @return The exit code of the command
+ * @throws JSchException
+ * @throws IOException
+ */
+ private int executeCommand(String command, StringBuilder output) throws JSchException, IOException
+ {
+ ensureSession();
+ ChannelExec channel = (ChannelExec) session.openChannel("exec");
+
+ channel.setCommand(command);
+ channel.setInputStream(null);
+ final InputStreamReader stream = new InputStreamReader(channel.getInputStream());
+ channel.setErrStream(System.err, true);
+ channel.connect();
+
+ // Read the stream
+ char[] buffer = new char[128];
+ int read;
+ while ((read = stream.read(buffer, 0, buffer.length)) >= 0)
+ {
+ output.append(buffer, 0, read);
+ }
+ stream.close();
+
+ // Wait until the command finishes (should not be long since we read the output stream)
+ while (!channel.isClosed()) {
+ try{Thread.sleep(100);} catch(Exception ee){}
+ }
+
+ channel.disconnect();
+
+ return channel.getExitStatus();
+ }
}
Added: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java?rev=1362045&view=auto
==============================================================================
--- commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java (added)
+++ commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java Mon Jul 16 14:10:39 2012
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.vfs2.util;
+
+import org.apache.commons.vfs2.FileSystemException;
+
+import java.io.IOException;
+import java.util.EnumMap;
+import java.util.Map;
+
+
+/**
+ * UNIX permissions.
+ *
+ * @since 2.1
+ */
+public class PosixPermissions
+{
+
+
+ static public enum Type
+ {
+ // User rights
+ UserReadable(00400),
+ UserWritable(00200),
+ UserExecutable(00100),
+
+ // Group rights
+ GroupReadable(00040),
+ GroupWritable(00020),
+ GroupExecutable(00010),
+
+ // Other rights
+ OtherReadable(00004),
+ OtherWritable(00002),
+ OtherExecutable(00001);
+
+ final private int mask;
+
+ /**
+ * Initialise with the mask
+ */
+ private Type(int mask)
+ {
+ this.mask = mask;
+ }
+
+ /**
+ * Return the mask for this permission
+ */
+ public int getMask()
+ {
+ return mask;
+ }
+
+ }
+
+ /**
+ * Current permissions
+ */
+ int permissions;
+
+ /**
+ * If the user is the owner of the file
+ */
+ boolean isOwner;
+
+ /**
+ * If one user group is the group of the file
+ */
+ boolean isInGroup;
+
+
+ /**
+ * Creates a new PosixPermissions object
+ * @param permissions The permissions
+ * @param isOwner true if the user is the owner of the file
+ * @param isInGroup true if the user is a group owner of the file
+ */
+ public PosixPermissions(int permissions, boolean isOwner, boolean isInGroup)
+ {
+ this.permissions = permissions;
+ this.isOwner = isOwner;
+ this.isInGroup = isInGroup;
+ }
+
+ public int getPermissions()
+ {
+ return permissions;
+ }
+
+
+ /**
+ * Computes new permission from old ones
+ *
+ * @param values The permissions to set
+ * @return The new permission
+ */
+ private int computeNewPermissions(Map<Type, Boolean> values)
+ {
+ int old = this.permissions;
+ for (Map.Entry<Type, Boolean> entry : values.entrySet())
+ {
+ final Type type = entry.getKey();
+ if (entry.getValue())
+ {
+ old |= type.getMask();
+ } else
+ {
+ old &= ~type.getMask();
+ }
+ }
+
+ return old;
+ }
+
+
+ /**
+ * Test whether the bit corresponding to the permission is set
+ */
+ private boolean get(Type type)
+ {
+ return (type.getMask() & permissions) != 0;
+ }
+
+ /**
+ * Check if whether the user can read the file
+ *
+ * @return true if the user can read
+ */
+ public boolean isReadable()
+ {
+ if (isOwner)
+ {
+ return get(Type.UserReadable);
+ }
+ if (isInGroup)
+ {
+ return get(Type.GroupReadable);
+ }
+ return get(Type.OtherReadable);
+ }
+
+
+ public Integer makeReadable(boolean readable, boolean ownerOnly)
+ {
+ EnumMap<Type, Boolean> map = new EnumMap<Type, Boolean>(Type.class);
+ map.put(Type.UserReadable, readable);
+ if (!ownerOnly)
+ {
+ map.put(Type.GroupReadable, readable);
+ map.put(Type.OtherReadable, readable);
+ }
+
+ return this.computeNewPermissions(map);
+ }
+
+ public boolean isWritable()
+ {
+ if (isOwner)
+ {
+ return get(Type.UserWritable);
+ }
+ if (isInGroup)
+ {
+ return get(Type.GroupWritable);
+ }
+ return get(Type.OtherWritable);
+ }
+
+ public Integer makeWritable(boolean writable, boolean ownerOnly)
+ {
+ EnumMap<Type, Boolean> map = new EnumMap<Type, Boolean>(Type.class);
+ map.put(Type.UserWritable, writable);
+ if (!ownerOnly)
+ {
+ map.put(Type.GroupWritable, writable);
+ map.put(Type.OtherWritable, writable);
+ }
+
+ return this.computeNewPermissions(map);
+ }
+
+ public boolean isExecutable()
+ {
+ if (isOwner)
+ {
+ return get(Type.UserExecutable);
+ }
+ if (isInGroup)
+ {
+ return get(Type.GroupExecutable);
+ }
+ return get(Type.OtherExecutable);
+ }
+
+ public int makeExecutable(boolean executable, boolean ownerOnly)
+ {
+ EnumMap<Type, Boolean> map = new EnumMap<Type, Boolean>(Type.class);
+ map.put(Type.UserExecutable, executable);
+ if (!ownerOnly)
+ {
+ map.put(Type.GroupExecutable, executable);
+ map.put(Type.OtherExecutable, executable);
+ }
+
+ return this.computeNewPermissions(map);
+ }
+}
Propchange: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/vfs/trunk/core/src/main/java/org/apache/commons/vfs2/util/PosixPermissions.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/local/test/LocalProviderTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/local/test/LocalProviderTestCase.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/local/test/LocalProviderTestCase.java (original)
+++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/local/test/LocalProviderTestCase.java Mon Jul 16 14:10:39 2012
@@ -24,6 +24,7 @@ import org.apache.commons.AbstractVfsTes
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs2.test.PermissionsTests;
import org.apache.commons.vfs2.test.ProviderTestConfig;
import org.apache.commons.vfs2.test.ProviderTestSuite;
Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java (original)
+++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java Mon Jul 16 14:10:39 2012
@@ -16,13 +16,14 @@
*/
package org.apache.commons.vfs2.provider.sftp.test;
-import java.io.File;
-import java.io.IOException;
+import java.io.*;
import java.net.InetSocketAddress;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
+import java.util.TreeMap;
+import com.jcraft.jsch.SftpATTRS;
import junit.framework.Test;
import org.apache.commons.AbstractVfsTestCase;
@@ -30,6 +31,7 @@ import org.apache.commons.vfs2.FileObjec
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs2.test.PermissionsTests;
import org.apache.commons.vfs2.provider.sftp.SftpFileProvider;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
import org.apache.commons.vfs2.provider.sftp.TrustEveryoneUserInfo;
@@ -40,15 +42,11 @@ import org.apache.ftpserver.ftplet.FtpEx
import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.FileSystemFactory;
-import org.apache.sshd.server.FileSystemView;
-import org.apache.sshd.server.ForwardingFilter;
-import org.apache.sshd.server.PasswordAuthenticator;
-import org.apache.sshd.server.PublickeyAuthenticator;
-import org.apache.sshd.server.SshFile;
+import org.apache.sshd.server.*;
import org.apache.sshd.server.auth.UserAuthNone;
+import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.filesystem.NativeSshFile;
import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
@@ -62,7 +60,6 @@ import com.jcraft.jsch.TestIdentityRepos
* <p>
* Starts and stops an embedded Apache SSHd (MINA) server.
* </p>
- *
*/
public class SftpProviderTestCase extends AbstractProviderTestConfig
{
@@ -185,7 +182,21 @@ public class SftpProviderTestCase extend
Server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(tmpDir + "/key.ser"));
}
List<NamedFactory<Command>> list = new ArrayList<NamedFactory<Command>>(1);
- list.add(new SftpSubsystem.Factory());
+ list.add(new NamedFactory<Command>()
+ {
+
+ @Override
+ public String getName()
+ {
+ return "sftp";
+ }
+
+ @Override
+ public Command create()
+ {
+ return new MySftpSubsystem();
+ }
+ });
Server.setSubsystemFactories(list);
Server.setPasswordAuthenticator(new PasswordAuthenticator()
{
@@ -224,6 +235,8 @@ public class SftpProviderTestCase extend
return true;
}
});
+ // Allows the execution of commands
+ Server.setCommandFactory(new ScpCommandFactory(new TestCommandFactory()));
// HACK Start
// How do we really do simple user to directory matching?
Server.setFileSystemFactory(new TestFileSystemFactory());
@@ -234,6 +247,7 @@ public class SftpProviderTestCase extend
// Do this after we start the server to simplify this set up code.
Server.getUserAuthFactories().add(new UserAuthNone.Factory());
// HACK End
+
}
/**
@@ -241,7 +255,7 @@ public class SftpProviderTestCase extend
*/
public static Test suite() throws Exception
{
- return new ProviderTestSuite(new SftpProviderTestCase())
+ final ProviderTestSuite suite = new ProviderTestSuite(new SftpProviderTestCase())
{
@Override
protected void setUp() throws Exception
@@ -260,6 +274,13 @@ public class SftpProviderTestCase extend
super.tearDown();
}
};
+
+
+ // VFS-405: set/get permissions
+ suite.addTests(PermissionsTests.class);
+
+ return suite;
+
}
/**
@@ -311,4 +332,246 @@ public class SftpProviderTestCase extend
{
manager.addProvider("sftp", new SftpFileProvider());
}
+
+
+ /**
+ * The command factory for the SSH server:
+ * Handles two commands: id -u and id -G
+ */
+ private static class TestCommandFactory extends ScpCommandFactory
+ {
+ public Command createCommand(final String command)
+ {
+ return new Command()
+ {
+ public ExitCallback callback = null;
+ public PrintStream out = null;
+ public PrintStream err = null;
+
+ @Override
+ public void setInputStream(InputStream in)
+ {
+ }
+
+ @Override
+ public void setOutputStream(OutputStream out)
+ {
+ this.out = new PrintStream(out);
+ }
+
+ @Override
+ public void setErrorStream(OutputStream err)
+ {
+ this.err = new PrintStream(err);
+ }
+
+ @Override
+ public void setExitCallback(ExitCallback callback)
+ {
+ this.callback = callback;
+
+ }
+
+ @Override
+ public void start(Environment env) throws IOException
+ {
+ int code = 0;
+ if (command.equals("id -G") || command.equals("id -u"))
+ {
+ out.println(0);
+ } else
+ {
+ if (err != null)
+ {
+ err.format("Unknown command %s%n", command);
+ }
+ code = -1;
+ }
+ if (out != null)
+ {
+ out.flush();
+ }
+ if (err != null)
+ {
+ err.flush();
+ }
+ callback.onExit(code);
+ }
+
+ @Override
+ public void destroy()
+ {
+ }
+ };
+ }
+ }
+
+
+ private static class SftpAttrs
+ {
+ int flags = 0;
+ private int uid;
+ long size = 0;
+ private int gid;
+ private int atime;
+ private int permissions;
+ private int mtime;
+ private String[] extended;
+
+ private SftpAttrs(Buffer buf)
+ {
+ int flags = 0;
+ flags = buf.getInt();
+
+ if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_SIZE) != 0)
+ {
+ size = buf.getLong();
+ }
+ if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_UIDGID) != 0)
+ {
+ uid = buf.getInt();
+ gid = buf.getInt();
+ }
+ if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) != 0)
+ {
+ permissions = buf.getInt();
+ }
+ if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) != 0)
+ {
+ atime = buf.getInt();
+ }
+ if ((flags & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) != 0)
+ {
+ mtime = buf.getInt();
+ }
+
+ }
+ }
+
+ private static class MySftpSubsystem extends SftpSubsystem
+ {
+ TreeMap<String, Integer> permissions = new TreeMap<String, Integer>();
+ private int _version;
+
+ @Override
+ protected void process(Buffer buffer) throws IOException
+ {
+ int rpos = buffer.rpos();
+ int length = buffer.getInt();
+ int type = buffer.getByte();
+ int id = buffer.getInt();
+
+ switch (type)
+ {
+ case SSH_FXP_SETSTAT:
+ case SSH_FXP_FSETSTAT:
+ {
+ // Get the path
+ String path = buffer.getString();
+ // Get the permission
+ SftpAttrs attrs = new SftpAttrs(buffer);
+ permissions.put(path, attrs.permissions);
+// System.err.format("Setting [%s] permission to %o%n", path, attrs.permissions);
+ break;
+ }
+
+ case SSH_FXP_REMOVE:
+ {
+ // Remove cached attributes
+ String path = buffer.getString();
+ permissions.remove(path);
+// System.err.format("Removing [%s] permission cache%n", path);
+ break;
+ }
+
+ case SSH_FXP_INIT:
+ {
+ // Just grab the version here
+ this._version = id;
+ break;
+ }
+ }
+
+ buffer.rpos(rpos);
+ super.process(buffer);
+
+ }
+
+ protected void writeAttrs(Buffer buffer, SshFile file, int flags) throws IOException
+ {
+ if (!file.doesExist()) {
+ throw new FileNotFoundException(file.getAbsolutePath());
+ }
+
+
+ int p = 0;
+
+ final Integer cached = permissions.get(file.getAbsolutePath());
+ if (cached != null)
+ {
+ // Use cached permissions
+// System.err.format("Using cached [%s] permission of %o%n", file.getAbsolutePath(), cached);
+ p |= cached;
+ } else
+ {
+ // Use permissions from Java file
+ if (file.isReadable())
+ {
+ p |= S_IRUSR;
+ }
+ if (file.isWritable())
+ {
+ p |= S_IWUSR;
+ }
+ if (file.isExecutable())
+ {
+ p |= S_IXUSR;
+ }
+ }
+
+ if (_version >= 4)
+ {
+ long size = file.getSize();
+// String username = session.getUsername();
+ long lastModif = file.getLastModified();
+ if (file.isFile())
+ {
+ buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS);
+ buffer.putByte((byte) SSH_FILEXFER_TYPE_REGULAR);
+ buffer.putInt(p);
+ } else if (file.isDirectory()) {
+ buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS);
+ buffer.putByte((byte) SSH_FILEXFER_TYPE_DIRECTORY);
+ buffer.putInt(p);
+ } else {
+ buffer.putInt(0);
+ buffer.putByte((byte) SSH_FILEXFER_TYPE_UNKNOWN);
+ }
+ } else {
+ if (file.isFile()) {
+ p |= 0100000;
+ }
+ if (file.isDirectory()) {
+ p |= 0040000;
+ }
+
+
+ if (file.isFile()) {
+ buffer.putInt(SSH_FILEXFER_ATTR_SIZE| SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
+ buffer.putLong(file.getSize());
+ buffer.putInt(p);
+ buffer.putInt(file.getLastModified()/1000);
+ buffer.putInt(file.getLastModified()/1000);
+ } else if (file.isDirectory()) {
+ buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
+ buffer.putInt(p);
+ buffer.putInt(file.getLastModified()/1000);
+ buffer.putInt(file.getLastModified()/1000);
+ } else {
+ buffer.putInt(0);
+ }
+ }
+ }
+
+ }
}
Added: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java?rev=1362045&view=auto
==============================================================================
--- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java (added)
+++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java Mon Jul 16 14:10:39 2012
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.test;
+
+import junit.framework.Assert;
+
+import org.apache.commons.lang3.SystemUtils;
+import org.apache.commons.vfs2.Capability;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.Selectors;
+import org.apache.commons.vfs2.provider.local.LocalFileSystem;
+
+import java.io.OutputStream;
+
+/**
+ * Additional naming tests for local file system.
+ *
+ * @since 2.1
+ */
+public class PermissionsTests extends AbstractProviderTestCase
+{
+
+ /**
+ * Returns the capabilities required by the tests of this test case.
+ */
+ @Override
+ protected Capability[] getRequiredCaps()
+ {
+ return new Capability[]
+ {
+ Capability.CREATE,
+ Capability.DELETE,
+ Capability.READ_CONTENT,
+ Capability.WRITE_CONTENT,
+ };
+ }
+
+ /**
+ * Tests for the execution permission.
+ */
+ public void testExecutable() throws Exception
+ {
+ final FileObject file = createTestFile();
+
+ // On Windows, all files are executable
+ if (isWindows())
+ {
+ Assert.assertTrue(file.isExecutable());
+
+ } else
+ {
+ // Set the executable flag
+ file.setExecutable(true, true);
+ Assert.assertTrue(file.isExecutable());
+
+ // Set the executable flag
+ file.setExecutable(true, false);
+ Assert.assertTrue(file.isExecutable());
+
+ // Clear the executable flag
+ file.setExecutable(false, true);
+ Assert.assertFalse(file.isExecutable());
+ }
+ }
+
+ /**
+ * Returns true if the filesystem is a Windows file system
+ */
+ private boolean isWindows()
+ {
+ return SystemUtils.IS_OS_WINDOWS && this.getFileSystem() instanceof LocalFileSystem;
+ }
+
+
+ /**
+ * Tests for the writeable permission
+ */
+ public void testWriteable() throws Exception
+ {
+ final FileObject file = createTestFile();
+
+ // Set the executable flag
+ file.setWritable(true, true);
+ Assert.assertTrue(file.isWriteable());
+
+ // Set the executable flag
+ file.setWritable(true, false);
+ Assert.assertTrue(file.isWriteable());
+
+ // Clear the executable flag
+ file.setWritable(false, true);
+ Assert.assertFalse(file.isWriteable());
+ }
+
+
+ /**
+ * Tests for the readable permission
+ */
+ public void testReadable() throws Exception
+ {
+ final FileObject file = createTestFile();
+
+ if (isWindows())
+ {
+ // On Windows, all owned files are readable
+ Assert.assertTrue(file.isReadable());
+ }
+ else
+ {
+ // Set the executable flag
+ System.err.println(file.setReadable(true, true));
+ Assert.assertTrue(file.isReadable());
+
+ // Set the executable flag
+ file.setReadable(true, false);
+ Assert.assertTrue(file.isReadable());
+
+ // Clear the executable flag
+ file.setReadable(false, true);
+ Assert.assertFalse(file.isReadable());
+ }
+ }
+
+
+ private FileObject createTestFile() throws Exception
+ {
+ // Get the scratch folder
+ FileObject scratchFolder = getWriteFolder();
+ assertNotNull(scratchFolder);
+
+ // Make sure the test folder is empty
+ scratchFolder.delete(Selectors.EXCLUDE_SELF);
+ scratchFolder.createFolder();
+
+ // Create direct child of the test folder
+ final FileObject file = scratchFolder.resolveFile("file1.txt");
+ assertTrue(!file.exists());
+
+ // Create the source file
+ final String content = "Here is some sample content for the file. Blah Blah Blah.";
+
+ final OutputStream os = file.getContent().getOutputStream();
+ try
+ {
+ os.write(content.getBytes("utf-8"));
+ }
+ finally
+ {
+ os.close();
+ }
+ return file;
+ }
+
+
+}
\ No newline at end of file
Propchange: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/test/PermissionsTests.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: commons/proper/vfs/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/pom.xml?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/pom.xml (original)
+++ commons/proper/vfs/trunk/pom.xml Mon Jul 16 14:10:39 2012
@@ -128,8 +128,8 @@
<commons.binary.suffix />
<commons.jira.id>VFS</commons.jira.id>
<commons.jira.pid>12310495</commons.jira.pid>
- <maven.compile.source>1.5</maven.compile.source>
- <maven.compile.target>1.5</maven.compile.target>
+ <maven.compile.source>1.6</maven.compile.source>
+ <maven.compile.target>1.6</maven.compile.target>
<commons.release.name>commons-vfs-${commons.release.version}</commons.release.name>
<vfs.parent.dir>${basedir}</vfs.parent.dir>
</properties>
@@ -153,13 +153,11 @@
</plugin>
<!-- Use 2.11 to run individual tests, 2.12 seems to no longer support this feature. -->
<!-- See http://jira.codehaus.org/browse/SUREFIRE-827 -->
- <!--
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
</plugin>
- -->
</plugins>
</pluginManagement>
<plugins>
Modified: commons/proper/vfs/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/src/changes/changes.xml?rev=1362045&r1=1362044&r2=1362045&view=diff
==============================================================================
--- commons/proper/vfs/trunk/src/changes/changes.xml (original)
+++ commons/proper/vfs/trunk/src/changes/changes.xml Mon Jul 16 14:10:39 2012
@@ -23,6 +23,12 @@
<body>
<release version="2.1" date="TBD" description="New features and bug fix release.">
+ <action issue="VFS-405" dev="ggregory" type="add" due-to="dwaszak">
+ Get/set the file permissions.
+ </action>
+ <action issue="VFS-415" dev="ggregory" type="add" due-to="ggregory">
+ Update VFS requirement to Java 1.6.
+ </action>
<action issue="VFS-426" dev="ggregory" type="add" due-to="daniel.bergholm">
HTTP URL query string not part of cache key.
</action>