com.pastdev.jsch.nio.file.UnixSshFileSystem Maven / Gradle / Ivy
package com.pastdev.jsch.nio.file;
import static com.pastdev.jsch.nio.file.UnixSshFileSystemProvider.PATH_SEPARATOR;
import static com.pastdev.jsch.nio.file.UnixSshFileSystemProvider.PATH_SEPARATOR_STRING;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileStore;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.WatchService;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.attribute.UserPrincipalNotFoundException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import com.jcraft.jsch.JSchException;
public class UnixSshFileSystem extends AbstractSshFileSystem {
private UnixSshPath defaultDirectory;
private UnixSshPath rootDirectory;
public UnixSshFileSystem( UnixSshFileSystemProvider provider, URI uri, Map environment ) throws IOException {
super( provider, uri, environment );
this.defaultDirectory = new UnixSshPath( this, uri.getPath() );
if ( !defaultDirectory.isAbsolute() ) {
throw new RuntimeException( "default directory must be absolute" );
}
rootDirectory = new UnixSshPath( this, PATH_SEPARATOR_STRING );
}
@Override
public void close() throws IOException {
getCommandRunner().close();
provider().removeFileSystem( this );
}
UnixSshPath getDefaultDirectory() {
return defaultDirectory;
}
@Override
public Iterable getFileStores() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Override
public UnixSshPath getPath( String first, String... more ) {
if ( more == null || more.length == 0 ) return new UnixSshPath( this, first );
StringBuilder builder = new StringBuilder( first );
for ( String part : more ) {
builder.append( PATH_SEPARATOR )
.append( part );
}
return new UnixSshPath( this, builder.toString() );
}
@Override
public PathMatcher getPathMatcher( String syntaxAndPattern ) {
int firstColon = syntaxAndPattern.indexOf( ':' );
if ( firstColon == -1 ) {
throw new IllegalArgumentException( "must be of the form 'syntax:pattern'" );
}
String syntax = syntaxAndPattern.substring( 0, firstColon );
String patternString = syntaxAndPattern.substring( firstColon + 1 );
if ( syntax.equalsIgnoreCase( "glob" ) ) {
StringBuilder builder = new StringBuilder().append( '^' );
char[] chars = patternString.toCharArray();
for ( int i = 0; i < chars.length; i++ ) {
char c = chars[i];
if ( c == '*' ) {
if ( chars[i + 1] == '*' ) {
builder.append( ".*" );
i++;
}
else {
builder.append( "[^/]*" );
}
}
else if ( c == '?' ) {
builder.append( '.' );
}
else if ( c == '{' ) {
builder.append( "(?:" );
while ( true ) {
if ( ++i < chars.length ) {
c = chars[i];
}
else {
throw new IllegalArgumentException( "invalid glob '" + patternString + "'" );
}
if ( c == ',' ) {
builder.append( '|' );
}
else if ( c == '}' ) {
break;
}
else {
builder.append( c );
}
}
builder.append( ")" );
}
else if ( c == '[' ) {
builder.append( '[' );
boolean first = true;
boolean caratEncountered = false;
while ( true ) {
if ( ++i < chars.length ) {
c = chars[i];
}
else {
throw new IllegalArgumentException( "invalid glob '" + patternString + "', unclosed range" );
}
if ( first ) {
if ( c == '!' ) {
builder.append( "^" );
}
else if ( c == '^' ) {
caratEncountered = true;
}
else {
builder.append( c );
}
first = false;
continue;
}
if ( c == ']' ) {
break;
}
else if ( c == '\\' ) {
builder.append( "\\\\" );
}
else {
builder.append( c );
}
}
if ( caratEncountered ) builder.append( '^' );
builder.append( ']' );
}
else if ( c == '\\' ) {
if ( ++i < chars.length ) {
builder.append( chars[i] );
}
else {
throw new IllegalArgumentException( "invalid glob '" + patternString + "'" );
}
}
else if ( c == '.' ) {
builder.append( "\\." );
}
else if ( c == '+' ) {
builder.append( "\\+" );
}
else if ( c == '(' ) {
builder.append( "\\(" );
}
else {
builder.append( c );
}
}
patternString = builder.append( '$' ).toString();
}
else if ( syntax.equalsIgnoreCase( "regex" ) ) {
// do nothing, pattern string is already regex
}
else {
throw new UnsupportedOperationException( "i dont have any clue what '" + syntax + "' is supposed to mean" );
}
final Pattern pattern = Pattern.compile( patternString );
return new PathMatcher() {
@Override
public boolean matches( Path path ) {
return pattern.matcher( path.toString() ).matches();
}
};
}
@Override
public Iterable getRootDirectories() {
return Collections.unmodifiableList(
Arrays.asList( new Path[] { rootDirectory } ) );
}
@Override
public String getSeparator() {
return PATH_SEPARATOR_STRING;
}
@Override
public UserPrincipalLookupService getUserPrincipalLookupService() {
return new UserPrincipalLookupService() {
@Override
public UserPrincipal lookupPrincipalByName( String user ) throws IOException {
try {
if ( getCommandRunner().execute( "id " + user ).getExitCode() == 0 ) {
return new StandardUserPrincipal( user );
}
else {
throw new UserPrincipalNotFoundException( user + " does not exist" );
}
}
catch ( JSchException e ) {
throw new IOException( e );
}
}
@Override
public GroupPrincipal lookupPrincipalByGroupName( String group ) throws IOException {
try {
// I don't like this, but don't have a better way right
// now...
// Should be pretty safe in most instances
if ( getCommandRunner().execute( "egrep -i \"^" + group + "\" /etc/group" ).getExitCode() == 0 ) {
return new StandardGroupPrincipal( group );
}
else {
throw new UserPrincipalNotFoundException( group + " does not exist" );
}
}
catch ( JSchException e ) {
throw new IOException( e );
}
}
};
}
@Override
public boolean isOpen() {
// command runner will just open a new session if the current session is
// closed, so it is effectively always open
return true;
}
@Override
public boolean isReadOnly() {
// TODO Auto-generated method stub
return false;
}
@Override
public WatchService newWatchService() throws IOException {
if ( getBooleanFromEnvironment( "watchservice.inotify" ) ) {
return UnixSshFileSystemWatchService.inotifyWatchService();
}
else {
// TODO make sure these values are set in environment, or get good
// defaults
return UnixSshFileSystemWatchService.pollingWatchService(
getLongFromEnvironment( "watchservice.polling.interval" ),
getTimeUnitFromEnvironment( "watchservice.polling.timeunit" ) );
}
}
@Override
public UnixSshFileSystemProvider provider() {
return (UnixSshFileSystemProvider)super.provider();
}
@Override
public Set supportedFileAttributeViews() {
Set supportedFileAttributeViews = new HashSet();
supportedFileAttributeViews.addAll( Arrays.asList( new String[] { "basic", "posix" } ) );
return Collections.unmodifiableSet( supportedFileAttributeViews );
}
}