Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .sdkmanrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
java=8-local
#java=21-local
maven=3.9.9
567 changes: 533 additions & 34 deletions integration-tests/src/test/java/no/maddin/niofs/it/FilesIT.java

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -353,5 +353,15 @@
</repository>
</distributionManagement>
</profile>
<profile>
<id>java8</id>
<activation>
<jdk>1.8</jdk>
</activation>
<properties>
<!-- java 8 generates wrong javadoc command line -->
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
</profile>
</profiles>
</project>
16 changes: 11 additions & 5 deletions sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileAttributeView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@

import java.io.IOException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.*;
import java.util.Arrays;

Check warning on line 7 in sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileAttributeView.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'java.util.Arrays'.

See more on https://sonarcloud.io/project/issues?id=maddingo_nio-fs-provider&issues=AZr6MrdiVcdC4SjUvOjx&open=AZr6MrdiVcdC4SjUvOjx&pullRequest=182
import java.util.Collections;

Check warning on line 8 in sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileAttributeView.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'java.util.Collections'.

See more on https://sonarcloud.io/project/issues?id=maddingo_nio-fs-provider&issues=AZr6MrdiVcdC4SjUvOjy&open=AZr6MrdiVcdC4SjUvOjy&pullRequest=182
import java.util.List;

Check warning on line 9 in sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileAttributeView.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import 'java.util.List'.

See more on https://sonarcloud.io/project/issues?id=maddingo_nio-fs-provider&issues=AZr6MrdiVcdC4SjUvOjz&open=AZr6MrdiVcdC4SjUvOjz&pullRequest=182
import java.util.Set;

public class SFTPFileAttributeView implements PosixFileAttributeView {
private final SFTPPath path;
private final SFTPFileSystemProvider provider;
private final List<LinkOption> options;
private final LinkOption[] options;

public SFTPFileAttributeView(SFTPFileSystemProvider sftpFileSystemProvider, SFTPPath path, LinkOption[] options) {
this.path = path;
this.provider = sftpFileSystemProvider;
this.options = options != null ? Arrays.asList(options) : Collections.emptyList();
this.options = options;
}

@Override
Expand All @@ -26,7 +27,12 @@

@Override
public UserPrincipal getOwner() throws IOException {
throw new UnsupportedOperationException();
BasicFileAttributes attributes = readAttributes();
if (!(attributes instanceof PosixFileAttributes)) {
throw new UnsupportedOperationException("File attributes are not PosixFileAttributes");
} else {
return ((PosixFileAttributes)attributes).owner();
}
}

@Override
Expand All @@ -36,12 +42,12 @@

@Override
public PosixFileAttributes readAttributes() throws IOException {
throw new UnsupportedOperationException();
return provider.readAttributes((Path)path, PosixFileAttributes.class, options);
}

@Override
public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException {
throw new UnsupportedOperationException();
provider.setTimes(path, lastModifiedTime, lastAccessTime, createTime);
}

@Override
Expand Down
147 changes: 147 additions & 0 deletions sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileAttributes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package no.maddin.niofs.sftp;

import com.jcraft.jsch.SftpATTRS;

import java.nio.file.attribute.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class SFTPFileAttributes implements PosixFileAttributes {
private final FileTime lastModifiedTime;
private final FileTime lastAccessTime;
private final FileTime creationTime;
private final boolean isRegularFile;
private final boolean isDirectory;
private final boolean isSymbolicLink;
private final boolean isOther;
private final long size;
private final Object fileKey;
private final String owner;
private final String group;
private final Set<PosixFilePermission> permissions;

SFTPFileAttributes(SftpATTRS stat) {
this.lastModifiedTime = FileTime.from(stat.getMTime(), TimeUnit.SECONDS);
this.lastAccessTime = FileTime.from(stat.getATime(), TimeUnit.SECONDS);
this.creationTime = FileTime.from(stat.getMTime(), TimeUnit.SECONDS);
this.isRegularFile = stat.isReg();
this.isDirectory = stat.isDir();
this.isSymbolicLink = stat.isLink();
this.isOther = !stat.isReg() && !stat.isDir() && !stat.isLink();
this.size = stat.getSize();
this.fileKey = null;
this.owner = String.valueOf(stat.getUId());
this.group = String.valueOf(stat.getGId());
this.permissions = asPermissions(stat.getPermissions());
}

@SuppressWarnings("java:S2612")
private static Set<PosixFilePermission> asPermissions(int permissions) {
Set<PosixFilePermission> result = EnumSet.noneOf(PosixFilePermission.class);

if ((permissions & 0_400) != 0) {
result.add(PosixFilePermission.OWNER_READ);
}
if ((permissions & 0_200) != 0) {
result.add(PosixFilePermission.OWNER_WRITE);
}
if ((permissions & 0_100) != 0) {
result.add(PosixFilePermission.OWNER_EXECUTE);
}
if ((permissions & 0_40) != 0) {
result.add(PosixFilePermission.GROUP_READ);
}
if ((permissions & 0_20) != 0) {
result.add(PosixFilePermission.GROUP_WRITE);
}
if ((permissions & 0_10) != 0) {
result.add(PosixFilePermission.GROUP_EXECUTE);
}
if ((permissions & 0_4) != 0) {
result.add(PosixFilePermission.OTHERS_READ);
}
if ((permissions & 0_2) != 0) {
result.add(PosixFilePermission.OTHERS_WRITE);
}
if ((permissions & 0_1) != 0) {
result.add(PosixFilePermission.OTHERS_EXECUTE);
}

return result;
}

public static Map<String, Object> asMap(SftpATTRS stat) {
SFTPFileAttributes attr = new SFTPFileAttributes(stat);
Map<String, Object> map = new HashMap<>();
map.put("lastModifiedTime", attr.lastModifiedTime);
map.put("lastAccessTime", attr.lastAccessTime);
map.put("creationTime", attr.creationTime);
map.put("isRegularFile", attr.isRegularFile);
map.put("isDirectory", attr.isDirectory);
map.put("isSymbolicLink", attr.isSymbolicLink);
map.put("isOther", attr.isOther);
map.put("size", attr.size);
map.put("fileKey", attr.fileKey);
return map;
}

@Override
public FileTime lastModifiedTime() {
return this.lastModifiedTime;
}

@Override
public FileTime lastAccessTime() {
return this.lastAccessTime;
}

@Override
public FileTime creationTime() {
return this.creationTime;
}

@Override
public boolean isRegularFile() {
return this.isRegularFile;
}

@Override
public boolean isDirectory() {
return this.isDirectory;
}

@Override
public boolean isSymbolicLink() {
return this.isSymbolicLink;
}

@Override
public boolean isOther() {
return this.isOther;
}

@Override
public long size() {
return this.size;
}

@Override
public Object fileKey() {
return this.fileKey;
}

@Override
public UserPrincipal owner() {
return () -> this.owner;
}

@Override
public GroupPrincipal group() {
return () -> this.group;
}

@Override
public Set<PosixFilePermission> permissions() {
return this.permissions;
}
}
91 changes: 91 additions & 0 deletions sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package no.maddin.niofs.sftp;

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.FileStoreAttributeView;
import java.util.Objects;

public class SFTPFileStore extends FileStore {
private final SFTPHost host;

public SFTPFileStore(SFTPHost host) {
this.host = host;
}

@Override
public String name() {
return host.toString();
}

@Override
public String type() {
return "sftp";
}

@Override
public boolean isReadOnly() {
return false;
}

@Override
public long getTotalSpace() throws IOException {
return Long.MAX_VALUE;
}

@Override
public long getUsableSpace() throws IOException {
return Long.MAX_VALUE;
}

@Override
public long getUnallocatedSpace() throws IOException {
return Long.MAX_VALUE;
}

@Override
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
return type == SFTPFileAttributeView.class;
}

@Override
public boolean supportsFileAttributeView(String name) {
return "posix".equals(name);
}

@Override
public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
return null;
}

@Override
public Object getAttribute(String attribute) throws IOException {
switch (attribute) {
case "totalSpace":
return getTotalSpace();
case "usableSpace":
return getUsableSpace();
case "unallocatedSpace":
return getUnallocatedSpace();
default:
throw new UnsupportedOperationException("Attribute '" + attribute + "' not supported");
}
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof SFTPFileStore)) {
return false;
}
SFTPFileStore other = (SFTPFileStore) obj;
return Objects.equals(host, other.host);
}

@Override
public int hashCode() {
return Objects.hash(host);
}
}
Loading
Loading