001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider.sftp;
018
019import java.io.File;
020import java.io.Serializable;
021import java.time.Duration;
022import java.util.Objects;
023import java.util.stream.Stream;
024
025import org.apache.commons.vfs2.FileSystem;
026import org.apache.commons.vfs2.FileSystemConfigBuilder;
027import org.apache.commons.vfs2.FileSystemException;
028import org.apache.commons.vfs2.FileSystemOptions;
029
030import com.jcraft.jsch.ConfigRepository;
031import com.jcraft.jsch.UserInfo;
032
033/**
034 * The config builder for various SFTP configuration options.
035 */
036public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder {
037
038    /**
039     * Proxy type.
040     */
041    public static final class ProxyType implements Serializable, Comparable<ProxyType> {
042        /**
043         * serialVersionUID format is YYYYMMDD for the date of the last binary change.
044         */
045        private static final long serialVersionUID = 20101208L;
046
047        private final String proxyType;
048
049        private ProxyType(final String proxyType) {
050            this.proxyType = proxyType;
051        }
052
053        @Override
054        public int compareTo(final ProxyType pType) {
055            return this.proxyType.compareTo(pType.proxyType);
056        }
057
058        @Override
059        public boolean equals(final Object obj) {
060            if (this == obj) {
061                return true;
062            }
063            if (obj == null || this.getClass() != obj.getClass()) {
064                return false;
065            }
066            return Objects.equals(this.proxyType, ((ProxyType) obj).proxyType);
067        }
068
069        /**
070         * @return a hash code value for this object.
071         * @since 2.0
072         */
073        @Override
074        public int hashCode() {
075            return this.proxyType.hashCode();
076        }
077    }
078    private static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ZERO;
079
080    private static final Duration DEFAULT_SESSION_TIMEOUT = Duration.ZERO;
081
082    private static final String _PREFIX = SftpFileSystemConfigBuilder.class.getName();
083    private static final SftpFileSystemConfigBuilder BUILDER = new SftpFileSystemConfigBuilder();
084    private static final String COMPRESSION = _PREFIX + "COMPRESSION";
085    private static final String CONNECT_TIMEOUT = _PREFIX + ".CONNECT_TIMEOUT";
086    private static final String ENCODING = _PREFIX + ".ENCODING";
087    private static final String HOST_KEY_CHECK_ASK = "ask";
088    private static final String HOST_KEY_CHECK_NO = "no";
089    private static final String HOST_KEY_CHECK_YES = "yes";
090    private static final String IDENTITIES = _PREFIX + ".IDENTITIES";
091    private static final String IDENTITY_REPOSITORY_FACTORY = _PREFIX + "IDENTITY_REPOSITORY_FACTORY";
092    private static final String CONFIG_REPOSITORY = _PREFIX + "CONFIG_REPOSITORY";
093    private static final String KEY_EXCHANGE_ALGORITHM = _PREFIX + ".KEY_EXCHANGE_ALGORITHM";
094    private static final String LOAD_OPENSSH_CONFIG = _PREFIX + "LOAD_OPENSSH_CONFIG";
095    private static final String KNOWN_HOSTS = _PREFIX + ".KNOWN_HOSTS";
096    private static final String PREFERRED_AUTHENTICATIONS = _PREFIX + ".PREFERRED_AUTHENTICATIONS";
097    private static final String PROXY_COMMAND = _PREFIX + ".PROXY_COMMAND";
098    private static final String PROXY_HOST = _PREFIX + ".PROXY_HOST";
099    private static final String PROXY_OPTIONS = _PREFIX + ".PROXY_OPTIONS";
100    private static final String PROXY_PASSWORD = _PREFIX + ".PROXY_PASSWORD";
101    private static final String PROXY_PORT = _PREFIX + ".PROXY_PORT";
102    private static final String DISABLE_DETECT_EXEC_CHANNEL = _PREFIX + ".DISABLE_DETECT_EXEC_CHANNEL";
103
104    /** HTTP Proxy. */
105    public static final ProxyType PROXY_HTTP = new ProxyType("http");
106
107    /** SOCKS Proxy. */
108    public static final ProxyType PROXY_SOCKS5 = new ProxyType("socks");
109
110    /**
111     * Connects to the SFTP server through a remote host reached by SSH.
112     * <p>
113     * On this proxy host, a command (e.g. {@linkplain SftpStreamProxy#NETCAT_COMMAND} or
114     * {@linkplain SftpStreamProxy#NETCAT_COMMAND}) is run to forward input/output streams between the target host and
115     * the VFS host.
116     * </p>
117     * <p>
118     * When used, the proxy username ({@linkplain #setProxyUser}) and hostname ({@linkplain #setProxyHost}) <b>must</b>
119     * be set. Optionnaly, the command ({@linkplain #setProxyCommand}), password ({@linkplain #setProxyPassword}) and
120     * connection options ({@linkplain #setProxyOptions}) can be set.
121     * </p>
122     */
123    public static final ProxyType PROXY_STREAM = new ProxyType("stream");
124
125    private static final String PROXY_TYPE = _PREFIX + ".PROXY_TYPE";
126    private static final String PROXY_USER = _PREFIX + ".PROXY_USER";
127    private static final String SESSION_TIMEOUT = _PREFIX + ".TIMEOUT";
128    private static final String STRICT_HOST_KEY_CHECKING = _PREFIX + ".STRICT_HOST_KEY_CHECKING";
129    private static final String USER_DIR_IS_ROOT = _PREFIX + ".USER_DIR_IS_ROOT";
130
131    /**
132     * Gets the singleton builder.
133     *
134     * @return the singleton builder.
135     */
136    public static SftpFileSystemConfigBuilder getInstance() {
137        return BUILDER;
138    }
139
140    private SftpFileSystemConfigBuilder() {
141        super("sftp.");
142    }
143
144    /**
145     * @param options The FileSystem options.
146     * @return The names of the compression algorithms, comma-separated.
147     * @see #setCompression
148     */
149    public String getCompression(final FileSystemOptions options) {
150        return this.getString(options, COMPRESSION);
151    }
152
153    @Override
154    protected Class<? extends FileSystem> getConfigClass() {
155        return SftpFileSystem.class;
156    }
157
158    /**
159     * Gets the config repository.
160     *
161     * @param options The FileSystem options.
162     * @return the ConfigRepository
163     */
164    public ConfigRepository getConfigRepository(final FileSystemOptions options) {
165        return getParam(options, CONFIG_REPOSITORY);
166    }
167
168    /**
169     * Gets the connect timeout duration.
170     *
171     * @param options The FileSystem options.
172     * @return The connect timeout duration.
173     * @see #setConnectTimeoutMillis
174     * @since 2.8.0
175     */
176    public Duration getConnectTimeout(final FileSystemOptions options) {
177        return this.getDuration(options, CONNECT_TIMEOUT, DEFAULT_CONNECT_TIMEOUT);
178    }
179
180    /**
181     * Gets the connect timeout duration.
182     *
183     * @param options The FileSystem options.
184     * @return The connect timeout value in milliseconds.
185     * @see #setConnectTimeoutMillis
186     * @since 2.3
187     * @deprecated Use {@link #getConnectTimeout(FileSystemOptions)}.
188     */
189    @Deprecated
190    public Integer getConnectTimeoutMillis(final FileSystemOptions options) {
191        return this.getDurationInteger(options, CONNECT_TIMEOUT, DEFAULT_CONNECT_TIMEOUT);
192    }
193
194    /**
195     * Gets the file name encoding.
196     *
197     * @param options The FileSystem options.
198     * @return the file name encoding
199     */
200    public String getFileNameEncoding(final FileSystemOptions options) {
201        return this.getString(options, ENCODING);
202    }
203
204    /**
205     * Gets the identity files (your private key files).
206     * <p>
207     * We use java.io.File because JSch cannot deal with VFS FileObjects.
208     * </p>
209     *
210     * @param options The FileSystem options.
211     * @return the array of identity Files.
212     * @see #setIdentities
213     * @deprecated As of 2.1 use {@link #getIdentityInfo(FileSystemOptions)}
214     */
215    @Deprecated
216    public File[] getIdentities(final FileSystemOptions options) {
217        final IdentityInfo[] info = getIdentityInfo(options);
218        if (info != null) {
219            return Stream.of(info).map(IdentityInfo::getPrivateKey).toArray(File[]::new);
220        }
221        return null;
222    }
223
224    /**
225     * Gets the identity infos.
226     *
227     * @param options The FileSystem options.
228     * @return the array of identity info.
229     * @see #setIdentityInfo
230     */
231    public IdentityInfo[] getIdentityInfo(final FileSystemOptions options) {
232        final IdentityProvider[] infos = getIdentityProvider(options);
233        if (infos != null) {
234            return Stream.of(infos).filter(info -> info instanceof IdentityInfo)
235                                   .map(info -> (IdentityInfo) info).toArray(IdentityInfo[]::new);
236        }
237        return null;
238    }
239
240    /**
241     * Gets the identity providers.
242     *
243     * @param options The FileSystem options.
244     * @return the array of identity providers.
245     * @see #setIdentityProvider
246     * @since 2.4
247     */
248    public IdentityProvider[] getIdentityProvider(final FileSystemOptions options) {
249        return getParam(options, IDENTITIES);
250    }
251
252    /**
253     * Get the identity repository factory.
254     *
255     * @param options The FileSystem options.
256     * @return the IdentityRepositoryFactory
257     */
258    public IdentityRepositoryFactory getIdentityRepositoryFactory(final FileSystemOptions options) {
259        return getParam(options, IDENTITY_REPOSITORY_FACTORY);
260    }
261
262    /**
263     * @param options The FileSystem options.
264     * @return the option value for specific key exchange algorithm
265     * @see #setKeyExchangeAlgorithm(FileSystemOptions, String)
266     * @since 2.4
267     */
268    public String getKeyExchangeAlgorithm(final FileSystemOptions options) {
269        return this.getString(options, KEY_EXCHANGE_ALGORITHM);
270    }
271
272
273    /**
274     * @param options The FileSystem options.
275     * @return the known hosts File.
276     * @see #setKnownHosts
277     */
278    public File getKnownHosts(final FileSystemOptions options) {
279        return getParam(options, KNOWN_HOSTS);
280    }
281
282    /**
283     * Gets authentication order.
284     *
285     * @param options The FileSystem options.
286     * @return The authentication order.
287     * @since 2.0
288     */
289    public String getPreferredAuthentications(final FileSystemOptions options) {
290        return getString(options, PREFERRED_AUTHENTICATIONS);
291    }
292
293    /**
294     * Gets the command that will be run on the proxy host when using a {@linkplain SftpStreamProxy}. The command
295     * defaults to {@linkplain SftpStreamProxy#NETCAT_COMMAND}.
296     *
297     * @param options The FileSystem options.
298     * @return proxyOptions
299     * @see SftpStreamProxy
300     * @see #setProxyOptions
301     * @since 2.1
302     */
303    public String getProxyCommand(final FileSystemOptions options) {
304        return this.getString(options, PROXY_COMMAND, SftpStreamProxy.NETCAT_COMMAND);
305    }
306
307    /**
308     * Gets the proxy to use for the SFTP connection.
309     *
310     * @param options The FileSystem options.
311     * @return proxyHost
312     * @see #getProxyPort
313     * @see #setProxyHost
314     */
315    public String getProxyHost(final FileSystemOptions options) {
316        return this.getString(options, PROXY_HOST);
317    }
318
319    /**
320     * Gets the proxy options that are used to connect to the proxy host.
321     *
322     * @param options The FileSystem options.
323     * @return proxyOptions
324     * @see SftpStreamProxy
325     * @see #setProxyOptions
326     * @since 2.1
327     */
328    public FileSystemOptions getProxyOptions(final FileSystemOptions options) {
329        return getParam(options, PROXY_OPTIONS);
330    }
331
332    /**
333     * Gets the proxy password that are used to connect to the proxy host.
334     *
335     * @param options The FileSystem options.
336     * @return proxyOptions
337     * @see SftpStreamProxy
338     * @see #setProxyPassword
339     * @since 2.1
340     */
341    public String getProxyPassword(final FileSystemOptions options) {
342        return this.getString(options, PROXY_PASSWORD);
343    }
344
345    /**
346     * Gets the proxy-port to use for the SFTP the connection.
347     *
348     * @param options The FileSystem options.
349     * @return proxyPort: the port number or 0 if it is not set
350     * @see #setProxyPort
351     * @see #getProxyHost
352     */
353    public int getProxyPort(final FileSystemOptions options) {
354        return this.getInteger(options, PROXY_PORT, 0);
355    }
356
357    /**
358     * Gets the proxy type to use for the SFTP connection.
359     *
360     * @param options The FileSystem options.
361     * @return The ProxyType.
362     */
363    public ProxyType getProxyType(final FileSystemOptions options) {
364        return getParam(options, PROXY_TYPE);
365    }
366
367    /**
368     * Gets the user name for the proxy used for the SFTP connection.
369     *
370     * @param options The FileSystem options.
371     * @return proxyUser
372     * @see #setProxyUser
373     * @since 2.1
374     */
375    public String getProxyUser(final FileSystemOptions options) {
376        return this.getString(options, PROXY_USER);
377    }
378
379    /**
380     * @param options The FileSystem options.
381     * @return The session timeout value in milliseconds.
382     * @see #setSessionTimeout
383     * @since 2.3
384     */
385    public Duration getSessionTimeout(final FileSystemOptions options) {
386        return this.getDuration(options, SESSION_TIMEOUT, DEFAULT_SESSION_TIMEOUT);
387    }
388
389    /**
390     * @param options The FileSystem options.
391     * @return The session timeout value in milliseconds.
392     * @see #setSessionTimeoutMillis
393     * @since 2.3
394     * @deprecated Use {@link #getSessionTimeout(FileSystemOptions)}.
395     */
396    @Deprecated
397    public Integer getSessionTimeoutMillis(final FileSystemOptions options) {
398        return this.getDurationInteger(options, SESSION_TIMEOUT, DEFAULT_SESSION_TIMEOUT);
399    }
400
401    /**
402     * @param options The FileSystem options.
403     * @return the option value The host key checking.
404     * @see #setStrictHostKeyChecking(FileSystemOptions, String)
405     */
406    public String getStrictHostKeyChecking(final FileSystemOptions options) {
407        return this.getString(options, STRICT_HOST_KEY_CHECKING, HOST_KEY_CHECK_NO);
408    }
409
410    /**
411     * @param options The FileSystem options.
412     * @return The timeout value in milliseconds.
413     * @see #setTimeout
414     * @deprecated Use {@link #getSessionTimeoutMillis(FileSystemOptions)}
415     */
416    @Deprecated
417    public Integer getTimeout(final FileSystemOptions options) {
418        return this.getInteger(options, SESSION_TIMEOUT);
419    }
420
421    /**
422     * Returns {@link Boolean#TRUE} if VFS should treat the user directory as the root directory. Defaults to
423     * {@code Boolean.TRUE} if the method {@link #setUserDirIsRoot(FileSystemOptions, boolean)} has not been
424     * invoked.
425     *
426     * @param options The FileSystemOptions.
427     * @return {@code Boolean.TRUE} if VFS treats the user directory as the root directory.
428     * @see #setUserDirIsRoot
429     */
430    public Boolean getUserDirIsRoot(final FileSystemOptions options) {
431        return this.getBoolean(options, USER_DIR_IS_ROOT, Boolean.TRUE);
432    }
433
434    /**
435     * @param options The FileSystem options.
436     * @return The UserInfo.
437     * @see #setUserInfo
438     */
439    public UserInfo getUserInfo(final FileSystemOptions options) {
440        return getParam(options, UserInfo.class.getName());
441    }
442
443    /**
444     * Returns {@code true} if the detection of the exec channel should be disabled.
445     * Returns {@code false} if the detection of the exec channel should be enabled.
446     * Defaults to {@code false} if the method {@link #setDisableDetectExecChannel(FileSystemOptions, boolean)} has not been invoked.
447     *
448     * @param options The FileSystemOptions.
449     * @return {@code true} if detection of exec channel should be disabled.
450     *
451     * @see #setDisableDetectExecChannel(FileSystemOptions, boolean)
452     * @since 2.7.0
453     */
454    public boolean isDisableDetectExecChannel(final FileSystemOptions options) {
455        return this.getBoolean(options, DISABLE_DETECT_EXEC_CHANNEL, Boolean.FALSE);
456    }
457
458    /**
459     * Returns {@link Boolean#TRUE} if VFS should load the OpenSSH config. Defaults to {@code Boolean.FALSE} if the
460     * method {@link #setLoadOpenSSHConfig(FileSystemOptions, boolean)} has not been invoked.
461     *
462     * @param options The FileSystemOptions.
463     * @return {@code Boolean.TRUE} if VFS should load the OpenSSH config.
464     * @see #setLoadOpenSSHConfig
465     */
466    public boolean isLoadOpenSSHConfig(final FileSystemOptions options) {
467        return this.getBoolean(options, LOAD_OPENSSH_CONFIG, Boolean.FALSE);
468    }
469
470    /**
471     * Configures the compression algorithms to use.
472     * <p>
473     * For example, use {@code "zlib,none"} to enable compression.
474     * </p>
475     * <p>
476     * See the Jsch documentation (in particular the README file) for details.
477     * </p>
478     *
479     * @param options        The FileSystem options.
480     * @param compression The names of the compression algorithms, comma-separated.
481     */
482    public void setCompression(final FileSystemOptions options, final String compression) {
483        this.setParam(options, COMPRESSION, compression);
484    }
485
486    /**
487     * Sets the config repository. e.g. {@code /home/user/.ssh/config}.
488     * <p>
489     * This is useful when you want to use OpenSSHConfig.
490     * </p>
491     *
492     * @param options             The FileSystem options.
493     * @param configRepository An config repository.
494     * @see <a href="http://www.jcraft.com/jsch/examples/OpenSSHConfig.java.html">OpenSSHConfig</a>
495     */
496    public void setConfigRepository(final FileSystemOptions options, final ConfigRepository configRepository) {
497        this.setParam(options, CONFIG_REPOSITORY, configRepository);
498    }
499
500    /**
501     * Sets the timeout value to create a Jsch connection.
502     *
503     * @param options    The FileSystem options.
504     * @param timeout The connect timeout in milliseconds.
505     * @since 2.8.0
506     */
507    public void setConnectTimeout(final FileSystemOptions options, final Duration timeout) {
508        this.setParam(options, CONNECT_TIMEOUT, timeout);
509    }
510
511    /**
512     * Sets the timeout value to create a Jsch connection.
513     *
514     * @param options    The FileSystem options.
515     * @param timeout The connect timeout in milliseconds.
516     * @since 2.3
517     * @deprecated Use {@link #setConnectTimeout(FileSystemOptions, Duration)}.
518     */
519    @Deprecated
520    public void setConnectTimeoutMillis(final FileSystemOptions options, final Integer timeout) {
521        this.setConnectTimeout(options, Duration.ofMillis(timeout));
522    }
523
524    /**
525     * Sets whether detection of exec channel is disabled.
526     * If this value is true the FileSystem will not test if the server allows to exec commands and disable the use of the exec channel.
527     *
528     * @param options        The FileSystem options.
529     * @param disableDetectExecChannel true if the detection of exec channel should be disabled.
530     * @since 2.7.0
531     */
532    public void setDisableDetectExecChannel(final FileSystemOptions options, final boolean disableDetectExecChannel) {
533        this.setParam(options, DISABLE_DETECT_EXEC_CHANNEL, toBooleanObject(disableDetectExecChannel));
534    }
535
536    /**
537     * Sets the file name encoding.
538     *
539     * @param options             The FileSystem options.
540     * @param fileNameEncoding The name of the encoding to use for file names.
541     */
542    public void setFileNameEncoding(final FileSystemOptions options, final String fileNameEncoding) {
543        this.setParam(options, ENCODING, fileNameEncoding);
544    }
545
546    /**
547     * Sets the identity files (your private key files).
548     * <p>
549     * We use {@link java.io.File} because JSch cannot deal with VFS FileObjects.
550     * </p>
551     *
552     * @param options          The FileSystem options.
553     * @param identityFiles An array of identity Files.
554     * @deprecated As of 2.1 use {@link #setIdentityInfo(FileSystemOptions, IdentityInfo...)}
555     */
556    @Deprecated
557    public void setIdentities(final FileSystemOptions options, final File... identityFiles) {
558        IdentityProvider[] info = null;
559        if (identityFiles != null) {
560            info = Stream.of(identityFiles).map(IdentityInfo::new).toArray(IdentityProvider[]::new);
561        }
562        this.setParam(options, IDENTITIES, info);
563    }
564
565    /**
566     * Sets the identity info (your private key files).
567     *
568     * @param options      The FileSystem options.
569     * @param identites An array of identity info.
570     * @since 2.1
571     * @deprecated Use {@link #setIdentityProvider(FileSystemOptions,IdentityProvider...)}
572     */
573    @Deprecated
574    public void setIdentityInfo(final FileSystemOptions options, final IdentityInfo... identites) {
575        this.setParam(options, IDENTITIES, identites);
576    }
577
578    /**
579     * Sets the identity info (your private key files).
580     *
581     * @param options      The FileSystem options.
582     * @param identites An array of identity info.
583     * @since 2.4
584     */
585    public void setIdentityProvider(final FileSystemOptions options, final IdentityProvider... identites) {
586        this.setParam(options, IDENTITIES, identites);
587    }
588
589    /**
590     * Sets the identity repository.
591     * <p>
592     * This is useful when you want to use e.g. an SSH agent as provided.
593     * </p>
594     *
595     * @param options    The FileSystem options.
596     * @param factory An identity repository.
597     * @see <a href="http://www.jcraft.com/jsch-agent-proxy/">JSch agent proxy</a>
598     */
599    public void setIdentityRepositoryFactory(final FileSystemOptions options, final IdentityRepositoryFactory factory) {
600        this.setParam(options, IDENTITY_REPOSITORY_FACTORY, factory);
601    }
602
603    /**
604     * Configures Key exchange algorithm explicitly e.g diffie-hellman-group14-sha1,
605     * diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1
606     *
607     * @param options                The FileSystem options.
608     * @param keyExchangeAlgoritm The key exchange algorithm picked.
609     * @since 2.4
610     */
611    public void setKeyExchangeAlgorithm(final FileSystemOptions options, final String keyExchangeAlgoritm) {
612        setParam(options, KEY_EXCHANGE_ALGORITHM, keyExchangeAlgoritm);
613    }
614
615    /**
616     * Sets the known_hosts file. e.g. {@code /home/user/.ssh/known_hosts2}.
617     * <p>
618     * We use {@link java.io.File} because JSch cannot deal with VFS FileObjects.
619     * </p>
620     *
621     * @param options       The FileSystem options.
622     * @param knownHosts The known hosts file.
623     */
624    public void setKnownHosts(final FileSystemOptions options, final File knownHosts) {
625        this.setParam(options, KNOWN_HOSTS, knownHosts);
626    }
627
628    /**
629     * Sets the whether to load OpenSSH config.
630     *
631     * @param options              The FileSystem options.
632     * @param loadOpenSSHConfig true if the OpenSSH config should be loaded.
633     */
634    public void setLoadOpenSSHConfig(final FileSystemOptions options, final boolean loadOpenSSHConfig) {
635        this.setParam(options, LOAD_OPENSSH_CONFIG, toBooleanObject(loadOpenSSHConfig));
636    }
637
638    /**
639     * Configures authentication order.
640     *
641     * @param options                     The FileSystem options.
642     * @param preferredAuthentications The authentication order.
643     * @since 2.0
644     */
645    public void setPreferredAuthentications(final FileSystemOptions options, final String preferredAuthentications) {
646        this.setParam(options, PREFERRED_AUTHENTICATIONS, preferredAuthentications);
647    }
648
649    /**
650     * Sets the proxy username to use for the SFTP connection.
651     *
652     * @param options         The FileSystem options.
653     * @param proxyCommand the port
654     * @see #getProxyOptions
655     * @since 2.1
656     */
657    public void setProxyCommand(final FileSystemOptions options, final String proxyCommand) {
658        this.setParam(options, PROXY_COMMAND, proxyCommand);
659    }
660
661    /**
662     * Sets the proxy to use for the SFTP connection.
663     *
664     * You MUST also set the proxy port to use the proxy.
665     *
666     * @param options      The FileSystem options.
667     * @param proxyHost the host
668     * @see #setProxyPort
669     */
670    public void setProxyHost(final FileSystemOptions options, final String proxyHost) {
671        this.setParam(options, PROXY_HOST, proxyHost);
672    }
673
674    /**
675     * Sets the proxy username to use for the SFTP connection.
676     *
677     * @param options         The FileSystem options.
678     * @param proxyOptions the options
679     * @see #getProxyOptions
680     * @since 2.1
681     */
682    public void setProxyOptions(final FileSystemOptions options, final FileSystemOptions proxyOptions) {
683        this.setParam(options, PROXY_OPTIONS, proxyOptions);
684    }
685
686    /**
687     * Sets the proxy password to use for the SFTP connection.
688     *
689     * @param options          The FileSystem options.
690     * @param proxyPassword the username used to connect to the proxy
691     * @see #getProxyPassword
692     * @since 2.1
693     */
694    public void setProxyPassword(final FileSystemOptions options, final String proxyPassword) {
695        this.setParam(options, PROXY_PASSWORD, proxyPassword);
696    }
697
698    /**
699     * Sets the proxy port to use for the SFTP connection.
700     * <p>
701     * You MUST also set the proxy host to use the proxy.
702     * </p>
703     *
704     * @param options      The FileSystem options.
705     * @param proxyPort the port
706     * @see #setProxyHost
707     */
708    public void setProxyPort(final FileSystemOptions options, final int proxyPort) {
709        this.setParam(options, PROXY_PORT, Integer.valueOf(proxyPort));
710    }
711
712    /**
713     * Sets the proxy type to use for the SFTP connection.
714     * <p>
715     * The possibles values are:
716     * </p>
717     * <ul>
718     * <li>{@linkplain #PROXY_HTTP} connects using an HTTP proxy</li>
719     * <li>{@linkplain #PROXY_SOCKS5} connects using an Socket5 proxy</li>
720     * <li>{@linkplain #PROXY_STREAM} connects through a remote host stream command</li>
721     * </ul>
722     *
723     * @param options      The FileSystem options.
724     * @param proxyType the type of the proxy to use.
725     */
726    public void setProxyType(final FileSystemOptions options, final ProxyType proxyType) {
727        this.setParam(options, PROXY_TYPE, proxyType);
728    }
729
730    /**
731     * Sets the proxy username to use for the SFTP connection.
732     *
733     * @param options      The FileSystem options.
734     * @param proxyUser the username used to connect to the proxy
735     * @see #getProxyUser
736     * @since 2.1
737     */
738    public void setProxyUser(final FileSystemOptions options, final String proxyUser) {
739        this.setParam(options, PROXY_USER, proxyUser);
740    }
741
742    /**
743     * Sets the timeout value on Jsch session.
744     *
745     * @param options    The FileSystem options.
746     * @param timeout The session timeout in milliseconds.
747     * @since 2.8.0
748     */
749    public void setSessionTimeout(final FileSystemOptions options, final Duration timeout) {
750        this.setParam(options, SESSION_TIMEOUT, timeout);
751    }
752
753    /**
754     * Sets the timeout value on Jsch session.
755     *
756     * @param options    The FileSystem options.
757     * @param timeout The session timeout in milliseconds.
758     * @since 2.3
759     * @deprecated Use {@link #setSessionTimeout(FileSystemOptions, Duration)}.
760     */
761    @Deprecated
762    public void setSessionTimeoutMillis(final FileSystemOptions options, final Integer timeout) {
763        this.setSessionTimeout(options, Duration.ofMillis(timeout));
764    }
765
766    /**
767     * Configures the host key checking to use.
768     * <p>
769     * Valid arguments are: {@code "yes"}, {@code "no"} and {@code "ask"}.
770     * </p>
771     * <p>
772     * See the jsch documentation for details.
773     * </p>
774     *
775     * @param options            The FileSystem options.
776     * @param hostKeyChecking The host key checking to use.
777     * @throws FileSystemException if an error occurs.
778     */
779    public void setStrictHostKeyChecking(final FileSystemOptions options, final String hostKeyChecking)
780            throws FileSystemException {
781        if (hostKeyChecking == null || (!hostKeyChecking.equals(HOST_KEY_CHECK_ASK)
782                && !hostKeyChecking.equals(HOST_KEY_CHECK_NO) && !hostKeyChecking.equals(HOST_KEY_CHECK_YES))) {
783            throw new FileSystemException("vfs.provider.sftp/StrictHostKeyChecking-arg.error", hostKeyChecking);
784        }
785
786        this.setParam(options, STRICT_HOST_KEY_CHECKING, hostKeyChecking);
787    }
788
789    /**
790     * Sets the timeout value on Jsch session.
791     *
792     * @param options    The FileSystem options.
793     * @param timeout The timeout in milliseconds.
794     * @deprecated Use {@link #setSessionTimeout(FileSystemOptions, Duration)}
795     */
796    @Deprecated
797    public void setTimeout(final FileSystemOptions options, final Integer timeout) {
798        this.setParam(options, SESSION_TIMEOUT, timeout);
799    }
800
801    /**
802     * Sets the whether to use the user directory as root (do not change to file system root).
803     *
804     * @param options          The FileSystem options.
805     * @param userDirIsRoot true if the user directory is the root directory.
806     */
807    public void setUserDirIsRoot(final FileSystemOptions options, final boolean userDirIsRoot) {
808        this.setParam(options, USER_DIR_IS_ROOT, toBooleanObject(userDirIsRoot));
809    }
810
811    /**
812     * Sets the Jsch UserInfo class to use.
813     *
814     * @param options The FileSystem options.
815     * @param info User information.
816     */
817    public void setUserInfo(final FileSystemOptions options, final UserInfo info) {
818        this.setParam(options, UserInfo.class.getName(), info);
819    }
820
821}