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