This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-vfs.git
commit 60779ef2f57f080d183bd797e0e27e26b7e3cd35 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Fri Jul 16 08:31:15 2021 -0400 Sort members. --- .../vfs2/provider/sftp/SftpClientFactory.java | 196 +++++++++--------- .../vfs2/provider/sftp/SftpFileNameParser.java | 14 +- .../vfs2/provider/sftp/SftpFileProvider.java | 8 +- .../commons/vfs2/provider/sftp/SftpFileSystem.java | 230 ++++++++++----------- .../provider/sftp/SftpRandomAccessContent.java | 66 +++--- .../vfs2/provider/sftp/TrustEveryoneUserInfo.java | 4 +- 6 files changed, 259 insertions(+), 259 deletions(-) diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java index 276c02a..348feaa 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java @@ -44,15 +44,80 @@ import com.jcraft.jsch.UserInfo; */ public final class SftpClientFactory { + /** Interface JSchLogger with JCL. */ + private static class JSchLogger implements Logger { + @Override + public boolean isEnabled(final int level) { + switch (level) { + case FATAL: + return LOG.isFatalEnabled(); + case ERROR: + return LOG.isErrorEnabled(); + case WARN: + return LOG.isDebugEnabled(); + case DEBUG: + return LOG.isDebugEnabled(); + case INFO: + return LOG.isInfoEnabled(); + default: + return LOG.isDebugEnabled(); + + } + } + + @Override + public void log(final int level, final String msg) { + switch (level) { + case FATAL: + LOG.fatal(msg); + break; + case ERROR: + LOG.error(msg); + break; + case WARN: + LOG.warn(msg); + break; + case DEBUG: + LOG.debug(msg); + break; + case INFO: + LOG.info(msg); + break; + default: + LOG.debug(msg); + } + } + } private static final String SSH_DIR_NAME = ".ssh"; private static final String OPENSSH_CONFIG_NAME = "config"; + private static final Log LOG = LogFactory.getLog(SftpClientFactory.class); static { JSch.setLogger(new JSchLogger()); } - private SftpClientFactory() { + private static void addIdentities(final JSch jsch, final File sshDir, final IdentityProvider[] identities) + throws FileSystemException { + if (identities != null) { + for (final IdentityProvider info : identities) { + addIdentity(jsch, info); + } + } else { + // Load the private key (rsa-key only) + final File privateKeyFile = new File(sshDir, "id_rsa"); + if (privateKeyFile.isFile() && privateKeyFile.canRead()) { + addIdentity(jsch, new IdentityInfo(privateKeyFile)); + } + } + } + + private static void addIdentity(final JSch jsch, final IdentityProvider identity) throws FileSystemException { + try { + identity.addIdentity(jsch); + } catch (final JSchException e) { + throw new FileSystemException("vfs.provider.sftp/load-private-key.error", identity, e); + } } /** @@ -166,59 +231,12 @@ public final class SftpClientFactory { return session; } - private static void addIdentities(final JSch jsch, final File sshDir, final IdentityProvider[] identities) - throws FileSystemException { - if (identities != null) { - for (final IdentityProvider info : identities) { - addIdentity(jsch, info); - } - } else { - // Load the private key (rsa-key only) - final File privateKeyFile = new File(sshDir, "id_rsa"); - if (privateKeyFile.isFile() && privateKeyFile.canRead()) { - addIdentity(jsch, new IdentityInfo(privateKeyFile)); - } - } - } - - private static void setConfigRepository(final JSch jsch, final File sshDir, final ConfigRepository configRepository, final boolean loadOpenSSHConfig) throws FileSystemException { - if (configRepository != null) { - jsch.setConfigRepository(configRepository); - } else if (loadOpenSSHConfig) { - try { - // loading openssh config (~/.ssh/config) - final ConfigRepository openSSHConfig = OpenSSHConfig.parseFile(new File(sshDir, OPENSSH_CONFIG_NAME).getAbsolutePath()); - jsch.setConfigRepository(openSSHConfig); - } catch (final IOException e) { - throw new FileSystemException("vfs.provider.sftp/load-openssh-config.error", e); - } - } - } - - private static void addIdentity(final JSch jsch, final IdentityProvider identity) throws FileSystemException { - try { - identity.addIdentity(jsch); - } catch (final JSchException e) { - throw new FileSystemException("vfs.provider.sftp/load-private-key.error", identity, e); - } + private static ProxyHTTP createProxyHTTP(final String proxyHost, final int proxyPort) { + return proxyPort == 0 ? new ProxyHTTP(proxyHost) : new ProxyHTTP(proxyHost, proxyPort); } - private static void setKnownHosts(final JSch jsch, final File sshDir, File knownHostsFile) - throws FileSystemException { - try { - if (knownHostsFile != null) { - jsch.setKnownHosts(knownHostsFile.getAbsolutePath()); - } else { - // Load the known hosts file - knownHostsFile = new File(sshDir, "known_hosts"); - if (knownHostsFile.isFile() && knownHostsFile.canRead()) { - jsch.setKnownHosts(knownHostsFile.getAbsolutePath()); - } - } - } catch (final JSchException e) { - throw new FileSystemException("vfs.provider.sftp/known-hosts.error", knownHostsFile.getAbsolutePath(), e); - } - + private static ProxySOCKS5 createProxySOCKS5(final String proxyHost, final int proxyPort) { + return proxyPort == 0 ? new ProxySOCKS5(proxyHost) : new ProxySOCKS5(proxyHost, proxyPort); } private static Proxy createStreamProxy(final String proxyHost, final int proxyPort, @@ -239,14 +257,6 @@ public final class SftpClientFactory { return new SftpStreamProxy(proxyCommand, proxyUser, proxyHost, proxyPort, proxyPassword, proxyOptions); } - private static ProxySOCKS5 createProxySOCKS5(final String proxyHost, final int proxyPort) { - return proxyPort == 0 ? new ProxySOCKS5(proxyHost) : new ProxySOCKS5(proxyHost, proxyPort); - } - - private static ProxyHTTP createProxyHTTP(final String proxyHost, final int proxyPort) { - return proxyPort == 0 ? new ProxyHTTP(proxyHost) : new ProxyHTTP(proxyHost, proxyPort); - } - /** * Finds the {@code .ssh} directory. * <p> @@ -293,48 +303,38 @@ public final class SftpClientFactory { return new File(""); } - /** Interface JSchLogger with JCL. */ - private static class JSchLogger implements Logger { - @Override - public boolean isEnabled(final int level) { - switch (level) { - case FATAL: - return LOG.isFatalEnabled(); - case ERROR: - return LOG.isErrorEnabled(); - case WARN: - return LOG.isDebugEnabled(); - case DEBUG: - return LOG.isDebugEnabled(); - case INFO: - return LOG.isInfoEnabled(); - default: - return LOG.isDebugEnabled(); - + private static void setConfigRepository(final JSch jsch, final File sshDir, final ConfigRepository configRepository, final boolean loadOpenSSHConfig) throws FileSystemException { + if (configRepository != null) { + jsch.setConfigRepository(configRepository); + } else if (loadOpenSSHConfig) { + try { + // loading openssh config (~/.ssh/config) + final ConfigRepository openSSHConfig = OpenSSHConfig.parseFile(new File(sshDir, OPENSSH_CONFIG_NAME).getAbsolutePath()); + jsch.setConfigRepository(openSSHConfig); + } catch (final IOException e) { + throw new FileSystemException("vfs.provider.sftp/load-openssh-config.error", e); } } + } - @Override - public void log(final int level, final String msg) { - switch (level) { - case FATAL: - LOG.fatal(msg); - break; - case ERROR: - LOG.error(msg); - break; - case WARN: - LOG.warn(msg); - break; - case DEBUG: - LOG.debug(msg); - break; - case INFO: - LOG.info(msg); - break; - default: - LOG.debug(msg); + private static void setKnownHosts(final JSch jsch, final File sshDir, File knownHostsFile) + throws FileSystemException { + try { + if (knownHostsFile != null) { + jsch.setKnownHosts(knownHostsFile.getAbsolutePath()); + } else { + // Load the known hosts file + knownHostsFile = new File(sshDir, "known_hosts"); + if (knownHostsFile.isFile() && knownHostsFile.canRead()) { + jsch.setKnownHosts(knownHostsFile.getAbsolutePath()); + } } + } catch (final JSchException e) { + throw new FileSystemException("vfs.provider.sftp/known-hosts.error", knownHostsFile.getAbsolutePath(), e); } + + } + + private SftpClientFactory() { } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileNameParser.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileNameParser.java index 7d07523..769da95 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileNameParser.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileNameParser.java @@ -29,13 +29,6 @@ public class SftpFileNameParser extends URLFileNameParser { private static final SftpFileNameParser INSTANCE = new SftpFileNameParser(); /** - * Creates a new instance with a the default port 22. - */ - public SftpFileNameParser() { - super(DEFAULT_PORT); - } - - /** * Gets the singleton instance. * * @return the singleton instance. @@ -43,4 +36,11 @@ public class SftpFileNameParser extends URLFileNameParser { public static FileNameParser getInstance() { return INSTANCE; } + + /** + * Creates a new instance with a the default port 22. + */ + public SftpFileNameParser() { + super(DEFAULT_PORT); + } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileProvider.java index f4c56ee..e19fb60 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileProvider.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileProvider.java @@ -94,12 +94,12 @@ public class SftpFileProvider extends AbstractOriginatingFileProvider { } @Override - public FileSystemConfigBuilder getConfigBuilder() { - return SftpFileSystemConfigBuilder.getInstance(); + public Collection<Capability> getCapabilities() { + return capabilities; } @Override - public Collection<Capability> getCapabilities() { - return capabilities; + public FileSystemConfigBuilder getConfigBuilder() { + return SftpFileSystemConfigBuilder.getInstance(); } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java index 2c6778b..45b0d68 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystem.java @@ -101,6 +101,36 @@ public class SftpFileSystem extends AbstractFileSystem { } } + /** + * Adds the capabilities of this file system. + */ + @Override + protected void addCapabilities(final Collection<Capability> caps) { + caps.addAll(SftpFileProvider.capabilities); + } + + /** + * Creates a file object. This method is called only if the requested file is not cached. + */ + @Override + protected FileObject createFile(final AbstractFileName name) throws FileSystemException { + return new SftpFileObject(name, this); + } + + /** + * Some SFTP-only servers disable the exec channel. + * + * Attempt to detect this by calling getUid. + */ + private boolean detectExecDisabled() { + try { + return getUId() == UNIDENTIFED; + } catch(final JSchException | IOException e) { + LOG.debug("Cannot get UID, assuming no exec channel is present", e); + return true; + } + } + @Override protected void doCloseCommunicationLink() { if (idleChannel != null) { @@ -118,6 +148,47 @@ public class SftpFileSystem extends AbstractFileSystem { } /** + * Executes 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 if a JSch error is detected. + * @throws FileSystemException if a session cannot be created. + * @throws IOException if an I/O error is detected. + */ + private int executeCommand(final String command, final StringBuilder output) throws JSchException, IOException { + final ChannelExec channel = (ChannelExec) getSession().openChannel("exec"); + try { + channel.setCommand(command); + channel.setInputStream(null); + try (final InputStreamReader stream = new InputStreamReader(channel.getInputStream(), StandardCharsets.UTF_8)) { + channel.setErrStream(System.err, true); + channel.connect(DurationUtils.toMillisInt(connectTimeout)); + + // Read the stream + final char[] buffer = new char[EXEC_BUFFER_SIZE]; + int read; + while ((read = stream.read(buffer, 0, buffer.length)) >= 0) { + output.append(buffer, 0, read); + } + } + + // Wait until the command finishes (should not be long since we read the output stream) + while (!channel.isClosed()) { + try { + Thread.sleep(SLEEP_MILLIS); + } catch (final Exception ee) { + // TODO: swallow exception, really? + } + } + } finally { + channel.disconnect(); + } + return channel.getExitStatus(); + } + + /** * Returns an SFTP channel to the server. * * @return new or reused channel, never null. @@ -170,72 +241,6 @@ public class SftpFileSystem extends AbstractFileSystem { } /** - * Ensures that the session link is established. - * - * @throws FileSystemException if a session cannot be created. - */ - private Session getSession() throws FileSystemException { - if (!this.session.isConnected()) { - synchronized (this) { - if (!this.session.isConnected()) { - doCloseCommunicationLink(); - this.session = SftpFileProvider.createSession((GenericFileName) getRootName(), - getFileSystemOptions()); - } - } - } - return this.session; - } - - /** - * Returns a channel to the pool. - * - * @param channelSftp the SFTP channel. - */ - protected void putChannel(final ChannelSftp channelSftp) { - if (idleChannel == null) { - synchronized (this) { - if (idleChannel == null) { - // put back the channel only if it is still connected - if (channelSftp.isConnected() && !channelSftp.isClosed()) { - idleChannel = channelSftp; - } - } else { - channelSftp.disconnect(); - } - } - } else { - channelSftp.disconnect(); - } - } - - /** - * Adds the capabilities of this file system. - */ - @Override - protected void addCapabilities(final Collection<Capability> caps) { - caps.addAll(SftpFileProvider.capabilities); - } - - /** - * Creates a file object. This method is called only if the requested file is not cached. - */ - @Override - protected FileObject createFile(final AbstractFileName name) throws FileSystemException { - return new SftpFileObject(name, this); - } - - /** - * Last modification time is only an int and in seconds, thus can be off by 999. - * - * @return 1000 - */ - @Override - public double getLastModTimeAccuracy() { - return LAST_MOD_TIME_ACCURACY; - } - - /** * Gets the (numeric) group IDs. * * @return the (numeric) group IDs. @@ -270,6 +275,34 @@ public class SftpFileSystem extends AbstractFileSystem { } /** + * Last modification time is only an int and in seconds, thus can be off by 999. + * + * @return 1000 + */ + @Override + public double getLastModTimeAccuracy() { + return LAST_MOD_TIME_ACCURACY; + } + + /** + * Ensures that the session link is established. + * + * @throws FileSystemException if a session cannot be created. + */ + private Session getSession() throws FileSystemException { + if (!this.session.isConnected()) { + synchronized (this) { + if (!this.session.isConnected()) { + doCloseCommunicationLink(); + this.session = SftpFileProvider.createSession((GenericFileName) getRootName(), + getFileSystemOptions()); + } + } + } + return this.session; + } + + /** * Gets the (numeric) group IDs. * * @return The numeric user ID @@ -300,47 +333,6 @@ public class SftpFileSystem extends AbstractFileSystem { } /** - * Executes 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 if a JSch error is detected. - * @throws FileSystemException if a session cannot be created. - * @throws IOException if an I/O error is detected. - */ - private int executeCommand(final String command, final StringBuilder output) throws JSchException, IOException { - final ChannelExec channel = (ChannelExec) getSession().openChannel("exec"); - try { - channel.setCommand(command); - channel.setInputStream(null); - try (final InputStreamReader stream = new InputStreamReader(channel.getInputStream(), StandardCharsets.UTF_8)) { - channel.setErrStream(System.err, true); - channel.connect(DurationUtils.toMillisInt(connectTimeout)); - - // Read the stream - final char[] buffer = new char[EXEC_BUFFER_SIZE]; - int read; - while ((read = stream.read(buffer, 0, buffer.length)) >= 0) { - output.append(buffer, 0, read); - } - } - - // Wait until the command finishes (should not be long since we read the output stream) - while (!channel.isClosed()) { - try { - Thread.sleep(SLEEP_MILLIS); - } catch (final Exception ee) { - // TODO: swallow exception, really? - } - } - } finally { - channel.disconnect(); - } - return channel.getExitStatus(); - } - - /** * @return Whether the exec channel is disabled. * @see SftpFileSystem#execDisabled */ @@ -349,16 +341,24 @@ public class SftpFileSystem extends AbstractFileSystem { } /** - * Some SFTP-only servers disable the exec channel. + * Returns a channel to the pool. * - * Attempt to detect this by calling getUid. + * @param channelSftp the SFTP channel. */ - private boolean detectExecDisabled() { - try { - return getUId() == UNIDENTIFED; - } catch(final JSchException | IOException e) { - LOG.debug("Cannot get UID, assuming no exec channel is present", e); - return true; + protected void putChannel(final ChannelSftp channelSftp) { + if (idleChannel == null) { + synchronized (this) { + if (idleChannel == null) { + // put back the channel only if it is still connected + if (channelSftp.isConnected() && !channelSftp.isClosed()) { + idleChannel = channelSftp; + } + } else { + channelSftp.disconnect(); + } + } + } else { + channelSftp.disconnect(); } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpRandomAccessContent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpRandomAccessContent.java index 5eb0c32..4f2ecca 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpRandomAccessContent.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpRandomAccessContent.java @@ -45,25 +45,17 @@ class SftpRandomAccessContent extends AbstractRandomAccessStreamContent { } @Override - public long getFilePointer() throws IOException { - return filePointer; - } - - @Override - public void seek(final long pos) throws IOException { - if (pos == filePointer) { - // no change - return; - } - - if (pos < 0) { - throw new FileSystemException("vfs.provider/random-access-invalid-position.error", Long.valueOf(pos)); - } + public void close() throws IOException { if (dis != null) { - close(); - } + // mis.abort(); + mis.close(); - filePointer = pos; + // this is to avoid recursive close + final DataInputStream oldDis = dis; + dis = null; + oldDis.close(); + mis = null; + } } @Override @@ -76,6 +68,11 @@ class SftpRandomAccessContent extends AbstractRandomAccessStreamContent { mis = fileObject.getInputStream(filePointer); dis = new DataInputStream(new FilterInputStream(mis) { @Override + public void close() throws IOException { + SftpRandomAccessContent.this.close(); + } + + @Override public int read() throws IOException { final int ret = super.read(); if (ret > -1) { @@ -101,32 +98,35 @@ class SftpRandomAccessContent extends AbstractRandomAccessStreamContent { } return ret; } - - @Override - public void close() throws IOException { - SftpRandomAccessContent.this.close(); - } }); return dis; } @Override - public void close() throws IOException { - if (dis != null) { - // mis.abort(); - mis.close(); - - // this is to avoid recursive close - final DataInputStream oldDis = dis; - dis = null; - oldDis.close(); - mis = null; - } + public long getFilePointer() throws IOException { + return filePointer; } @Override public long length() throws IOException { return fileObject.getContent().getSize(); } + + @Override + public void seek(final long pos) throws IOException { + if (pos == filePointer) { + // no change + return; + } + + if (pos < 0) { + throw new FileSystemException("vfs.provider/random-access-invalid-position.error", Long.valueOf(pos)); + } + if (dis != null) { + close(); + } + + filePointer = pos; + } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/TrustEveryoneUserInfo.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/TrustEveryoneUserInfo.java index 7958659..1790c31 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/TrustEveryoneUserInfo.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/TrustEveryoneUserInfo.java @@ -38,13 +38,13 @@ public class TrustEveryoneUserInfo implements UserInfo { } @Override - public boolean promptPassword(final String s) { + public boolean promptPassphrase(final String s) { log.info(s + " - Answer: False"); return false; } @Override - public boolean promptPassphrase(final String s) { + public boolean promptPassword(final String s) { log.info(s + " - Answer: False"); return false; }