View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.provider.sftp;
18  
19  import java.io.File;
20  import java.io.Serializable;
21  
22  import org.apache.commons.vfs2.FileSystem;
23  import org.apache.commons.vfs2.FileSystemConfigBuilder;
24  import org.apache.commons.vfs2.FileSystemException;
25  import org.apache.commons.vfs2.FileSystemOptions;
26  
27  import com.jcraft.jsch.UserInfo;
28  
29  /**
30   * The config builder for various SFTP configuration options.
31   */
32  public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder
33  {
34      /**
35       * Proxy type.
36       */
37      public static final class ProxyType implements Serializable, Comparable<ProxyType>
38      {
39          /**
40           * serialVersionUID format is YYYYMMDD for the date of the last binary change.
41           */
42          private static final long serialVersionUID = 20101208L;
43  
44          private final String proxyType;
45  
46          private ProxyType(final String proxyType)
47          {
48              this.proxyType = proxyType;
49          }
50  
51          @Override
52          public int compareTo(final ProxyType pType)
53          {
54              return this.proxyType.compareTo(pType.proxyType);
55          }
56  
57          @Override
58          public boolean equals(final Object obj)
59          {
60              if (this == obj)
61              {
62                  return true;
63              }
64              if (obj == null || this.getClass() != obj.getClass())
65              {
66                  return false;
67              }
68  
69              final ProxyType pType = (ProxyType) obj;
70  
71              if (this.proxyType != null ? !this.proxyType.equals(pType.proxyType) : pType.proxyType != null)
72              {
73                  return false;
74              }
75  
76              return true;
77          }
78  
79          /**
80           * @return a hash code value for this object.
81           * @since 2.0
82           */
83          @Override
84          public int hashCode()
85          {
86              return this.proxyType.hashCode();
87          }
88      }
89  
90      /** HTTP Proxy. */
91      public static final ProxyType PROXY_HTTP = new ProxyType("http");
92  
93      /** SOCKS Proxy. */
94      public static final ProxyType PROXY_SOCKS5 = new ProxyType("socks");
95  
96      /**
97       * Connects to the SFTP server through a remote host reached by SSH.
98       * <p>
99       * On this proxy host, a command
100      * (e.g. {@linkplain SftpStreamProxy#NETCAT_COMMAND}
101      * or {@linkplain SftpStreamProxy#NETCAT_COMMAND}) is run to forward
102      * input/output streams between the target host and the VFS host.
103      * <p>
104      * When used, the proxy username ({@linkplain #setProxyUser}) and
105      * hostname ({@linkplain #setProxyHost}) <b>must</b> be set.
106      * Optionnaly, the command ({@linkplain #setProxyCommand}),
107      * password ({@linkplain #setProxyPassword}) and connection options
108      * ({@linkplain #setProxyOptions}) can be set.
109      */
110     public static final ProxyType PROXY_STREAM = new ProxyType("stream");
111 
112     private static final String _PREFIX = SftpFileSystemConfigBuilder.class.getName();
113     private static final SftpFileSystemConfigBuilder BUILDER = new SftpFileSystemConfigBuilder();
114     private static final String COMPRESSION = _PREFIX + "COMPRESSION";
115     private static final String HOST_KEY_CHECK_ASK = "ask";
116     private static final String HOST_KEY_CHECK_NO = "no";
117     private static final String HOST_KEY_CHECK_YES = "yes";
118     private static final String IDENTITIES = _PREFIX + ".IDENTITIES";
119     private static final String IDENTITY_REPOSITORY_FACTORY = _PREFIX + "IDENTITY_REPOSITORY_FACTORY";
120     private static final String KNOWN_HOSTS = _PREFIX + ".KNOWN_HOSTS";
121     private static final String PREFERRED_AUTHENTICATIONS = _PREFIX + ".PREFERRED_AUTHENTICATIONS";
122 
123     private static final String PROXY_HOST = _PREFIX + ".PROXY_HOST";
124     private static final String PROXY_USER = _PREFIX + ".PROXY_USER";
125     private static final String PROXY_OPTIONS = _PREFIX + ".PROXY_OPTIONS";
126     private static final String PROXY_TYPE = _PREFIX + ".PROXY_TYPE";
127     private static final String PROXY_PORT = _PREFIX + ".PROXY_PORT";
128     private static final String PROXY_PASSWORD = _PREFIX + ".PROXY_PASSWORD";
129     private static final String PROXY_COMMAND = _PREFIX + ".PROXY_COMMAND";
130 
131     private static final String STRICT_HOST_KEY_CHECKING = _PREFIX + ".STRICT_HOST_KEY_CHECKING";
132     private static final String TIMEOUT = _PREFIX + ".TIMEOUT";
133     private static final String USER_DIR_IS_ROOT = _PREFIX + ".USER_DIR_IS_ROOT";
134     private static final String ENCODING = _PREFIX + ".ENCODING";
135 
136     private SftpFileSystemConfigBuilder()
137     {
138         super("sftp.");
139     }
140 
141     /**
142      * Gets the singleton builder.
143      *
144      * @return the singleton builder.
145      */
146     public static SftpFileSystemConfigBuilder getInstance()
147     {
148         return BUILDER;
149     }
150 
151     /**
152      * @param opts
153      *            The FileSystem options.
154      * @return The names of the compression algorithms, comma-separated.
155      * @see #setCompression
156      */
157     public String getCompression(final FileSystemOptions opts)
158     {
159         return this.getString(opts, COMPRESSION);
160     }
161 
162     @Override
163     protected Class<? extends FileSystem> getConfigClass()
164     {
165         return SftpFileSystem.class;
166     }
167 
168     /**
169      * Gets the file name encoding.
170      *
171      * @param opts
172      *            The FileSystem options.
173      * @return the file name encoding
174      */
175     public String getFileNameEncoding(final FileSystemOptions opts)
176     {
177         return this.getString(opts, ENCODING);
178     }
179 
180     /**
181      * Gets the identity files (your private key files).
182      * <p>
183      * We use java.io.File because JSch cannot deal with VFS FileObjects.
184      *
185      * @param opts The FileSystem options.
186      * @return the array of identity Files.
187      * @see #setIdentities
188      * @deprecated As of 2.1 use {@link #getIdentityInfo(FileSystemOptions)}
189      */
190     @Deprecated
191     public File[] getIdentities(final FileSystemOptions opts)
192     {
193         final IdentityInfo[] info = getIdentityInfo(opts);
194         if (info != null)
195         {
196             final File[] files = new File[info.length];
197             for (int i = 0; i < files.length; ++i)
198             {
199                 files[i] = info[i].getPrivateKey();
200             }
201             return files;
202         }
203         return null;
204     }
205 
206     /**
207      * Gets the identity info.
208      *
209      * @param opts
210      *            The FileSystem options.
211      * @return the array of identity info instances.
212      * @see #setIdentityInfo
213      */
214     public IdentityInfo[] getIdentityInfo(final FileSystemOptions opts)
215     {
216         return (IdentityInfo[]) this.getParam(opts, IDENTITIES);
217     }
218 
219     /**
220      * Get the identity repository factory.
221      *
222      * @param opts
223      *            The FileSystem options.
224      * @return the IdentityRepositoryFactory
225      */
226     public IdentityRepositoryFactory getIdentityRepositoryFactory(final FileSystemOptions opts)
227     {
228         return (IdentityRepositoryFactory) this.getParam(opts, IDENTITY_REPOSITORY_FACTORY);
229     }
230 
231     /**
232      * @param opts
233      *            The FileSystem options.
234      * @return the known hosts File.
235      * @see #setKnownHosts
236      */
237     public File getKnownHosts(final FileSystemOptions opts)
238     {
239         return (File) this.getParam(opts, KNOWN_HOSTS);
240     }
241 
242     /**
243      * Gets authentication order.
244      *
245      * @param opts
246      *            The FileSystem options.
247      * @return The authentication order.
248      * @since 2.0
249      */
250     public String getPreferredAuthentications(final FileSystemOptions opts)
251     {
252         return getString(opts, PREFERRED_AUTHENTICATIONS);
253     }
254 
255     /**
256      * Gets the command that will be run on the proxy
257      * host when using a {@linkplain SftpStreamProxy}. The
258      * command defaults to {@linkplain SftpStreamProxy#NETCAT_COMMAND}.
259      *
260      * @param opts
261      *            The FileSystem options.
262      * @return proxyOptions
263      * @see SftpStreamProxy
264      * @see #setProxyOptions
265      * @since 2.1
266      */
267     public String getProxyCommand(final FileSystemOptions opts)
268     {
269         return this.getString(opts, PROXY_COMMAND, SftpStreamProxy.NETCAT_COMMAND);
270     }
271 
272     /**
273      * Gets the proxy to use for the SFTP connection.
274      *
275      * @param opts
276      *            The FileSystem options.
277      * @return proxyHost
278      * @see #getProxyPort
279      * @see #setProxyHost
280      */
281     public String getProxyHost(final FileSystemOptions opts)
282     {
283         return this.getString(opts, PROXY_HOST);
284     }
285 
286     /**
287      * Gets the proxy options that are used to connect
288      * to the proxy host.
289      *
290      * @param opts
291      *            The FileSystem options.
292      * @return proxyOptions
293      * @see SftpStreamProxy
294      * @see #setProxyOptions
295      * @since 2.1
296      */
297     public FileSystemOptions getProxyOptions(final FileSystemOptions opts)
298     {
299         return (FileSystemOptions) this.getParam(opts, PROXY_OPTIONS);
300     }
301 
302     /**
303      * Gets the proxy password that are used to connect
304      * to the proxy host.
305      *
306      * @param opts
307      *            The FileSystem options.
308      * @return proxyOptions
309      * @see SftpStreamProxy
310      * @see #setProxyPassword
311      * @since 2.1
312      */
313     public String getProxyPassword(final FileSystemOptions opts)
314     {
315         return this.getString(opts, PROXY_PASSWORD);
316     }
317 
318     /**
319      * Gets the proxy-port to use for the SFTP the connection.
320      *
321      * @param opts
322      *            The FileSystem options.
323      * @return proxyPort: the port number or 0 if it is not set
324      * @see #setProxyPort
325      * @see #getProxyHost
326      */
327     public int getProxyPort(final FileSystemOptions opts)
328     {
329         return this.getInteger(opts, PROXY_PORT, 0);
330     }
331 
332     /**
333      * Gets the proxy type to use for the SFTP connection.
334      *
335      * @param opts
336      *            The FileSystem options.
337      * @return The ProxyType.
338      */
339     public ProxyType getProxyType(final FileSystemOptions opts)
340     {
341         return (ProxyType) this.getParam(opts, PROXY_TYPE);
342     }
343 
344     /**
345      * Gets the user name for the proxy used for the SFTP connection.
346      *
347      * @param opts
348      *            The FileSystem options.
349      * @return proxyUser
350      * @see #setProxyUser
351      * @since 2.1
352      */
353     public String getProxyUser(final FileSystemOptions opts)
354     {
355         return this.getString(opts, PROXY_USER);
356     }
357 
358     /**
359      * @param opts
360      *            The FileSystem options.
361      * @return the option value The host key checking.
362      * @see #setStrictHostKeyChecking(FileSystemOptions, String)
363      */
364     public String getStrictHostKeyChecking(final FileSystemOptions opts)
365     {
366         return this.getString(opts, STRICT_HOST_KEY_CHECKING, HOST_KEY_CHECK_NO);
367     }
368 
369     /**
370      * @param opts
371      *            The FileSystem options.
372      * @return The timeout value in milliseconds.
373      * @see #setTimeout
374      */
375     public Integer getTimeout(final FileSystemOptions opts)
376     {
377         return this.getInteger(opts, TIMEOUT);
378     }
379 
380     /**
381      * Returns {@link Boolean#TRUE} if VFS should treat the user directory as the root directory. Defaults to
382      * <code>Boolean.TRUE</code> if the method {@link #setUserDirIsRoot(FileSystemOptions, boolean)} has not been
383      * invoked.
384      *
385      * @param opts
386      *            The FileSystemOptions.
387      * @return <code>Boolean.TRUE</code> if VFS treats the user directory as the root directory.
388      * @see #setUserDirIsRoot
389      */
390     public Boolean getUserDirIsRoot(final FileSystemOptions opts)
391     {
392         return this.getBoolean(opts, USER_DIR_IS_ROOT, Boolean.TRUE);
393     }
394 
395     /**
396      * @param opts
397      *            The FileSystem options.
398      * @return The UserInfo.
399      * @see #setUserInfo
400      */
401     public UserInfo getUserInfo(final FileSystemOptions opts)
402     {
403         return (UserInfo) this.getParam(opts, UserInfo.class.getName());
404     }
405 
406     /**
407      * Configures the compression algorithms to use.
408      * <p>
409      * For example, use {@code "zlib,none"} to enable compression.
410      * <p>
411      * See the Jsch documentation (in particular the README file) for details.
412      *
413      * @param opts
414      *            The FileSystem options.
415      * @param compression
416      *            The names of the compression algorithms, comma-separated.
417      * @throws FileSystemException
418      *             if an error occurs.
419      */
420     public void setCompression(final FileSystemOptions opts, final String compression) throws FileSystemException
421     {
422         this.setParam(opts, COMPRESSION, compression);
423     }
424 
425     /**
426      * Sets the file name encoding.
427      *
428      * @param opts The FileSystem options.
429      * @param fileNameEncoding The name of the encoding to use for file names.
430      */
431     public void setFileNameEncoding(final FileSystemOptions opts, final String fileNameEncoding)
432     {
433         this.setParam(opts, ENCODING, fileNameEncoding);
434     }
435 
436     /**
437      * Sets the identity files (your private key files).
438      * <p>
439      * We use {@link java.io.File} because JSch cannot deal with VFS FileObjects.
440      *
441      * @param opts The FileSystem options.
442      * @param identityFiles An array of identity Files.
443      * @throws FileSystemException if an error occurs.
444      * @deprecated As of 2.1 use {@link #setIdentityInfo(FileSystemOptions, IdentityInfo...)}
445      */
446     @Deprecated
447     public void setIdentities(final FileSystemOptions opts, final File... identityFiles)
448         throws FileSystemException
449     {
450         IdentityInfo[] info = null;
451         if (identityFiles != null)
452         {
453             info = new IdentityInfo[identityFiles.length];
454             for (int i = 0; i < identityFiles.length; i++)
455             {
456                 info[i] = new IdentityInfo(identityFiles[i]);
457             }
458         }
459         this.setParam(opts, IDENTITIES, info);
460     }
461 
462     /**
463      * Sets the identity info (your private key files).
464      *
465      * @param opts
466      *            The FileSystem options.
467      * @param identites
468      *            An array of identity info.
469      * @throws FileSystemException
470      *             if an error occurs.
471      * @since 2.1
472      */
473     public void setIdentityInfo(final FileSystemOptions opts, final IdentityInfo... identites)
474         throws FileSystemException
475     {
476         this.setParam(opts, IDENTITIES, identites);
477     }
478 
479     /**
480      * Set the identity repository.
481      * <p>
482      * This is useful when you want to use e.g. an SSH agent as provided.
483      *
484      * @param opts
485      *            The FileSystem options.
486      * @param factory
487      *            An identity repository.
488      * @throws FileSystemException
489      *             if an error occurs.
490      * @see <a href="http://www.jcraft.com/jsch-agent-proxy/">JSch agent proxy</a>
491      */
492     public void setIdentityRepositoryFactory(final FileSystemOptions opts, final IdentityRepositoryFactory factory)
493             throws FileSystemException
494     {
495         this.setParam(opts, IDENTITY_REPOSITORY_FACTORY, factory);
496     }
497 
498     /**
499      * Sets the known_hosts file. e.g. {@code /home/user/.ssh/known_hosts2}.
500      * <p>
501      * We use {@link java.io.File} because JSch cannot deal with VFS FileObjects.
502      *
503      * @param opts
504      *            The FileSystem options.
505      * @param knownHosts
506      *            The known hosts file.
507      * @throws FileSystemException
508      *             if an error occurs.
509      */
510     public void setKnownHosts(final FileSystemOptions opts, final File knownHosts) throws FileSystemException
511     {
512         this.setParam(opts, KNOWN_HOSTS, knownHosts);
513     }
514 
515     /**
516      * Configures authentication order.
517      *
518      * @param opts
519      *            The FileSystem options.
520      * @param preferredAuthentications
521      *            The authentication order.
522      * @since 2.0
523      */
524     public void setPreferredAuthentications(final FileSystemOptions opts, final String preferredAuthentications)
525     {
526         this.setParam(opts, PREFERRED_AUTHENTICATIONS, preferredAuthentications);
527     }
528 
529     /**
530      * Sets the proxy username to use for the SFTP connection.
531      *
532      * @param opts
533      *            The FileSystem options.
534      * @param proxyCommand
535      *            the port
536      * @see #getProxyOptions
537      * @since 2.1
538      */
539     public void setProxyCommand(final FileSystemOptions opts, final String proxyCommand)
540     {
541         this.setParam(opts, PROXY_COMMAND, proxyCommand);
542     }
543 
544     /**
545      * Sets the proxy to use for the SFTP connection.
546      *
547      * You MUST also set the proxy port to use the proxy.
548      *
549      * @param opts
550      *            The FileSystem options.
551      * @param proxyHost
552      *            the host
553      * @see #setProxyPort
554      */
555     public void setProxyHost(final FileSystemOptions opts, final String proxyHost)
556     {
557         this.setParam(opts, PROXY_HOST, proxyHost);
558     }
559 
560     /**
561      * Sets the proxy username to use for the SFTP connection.
562      *
563      * @param opts
564      *            The FileSystem options.
565      * @param proxyOptions
566      *            the options
567      * @see #getProxyOptions
568      * @since 2.1
569      */
570     public void setProxyOptions(final FileSystemOptions opts, final FileSystemOptions proxyOptions)
571     {
572         this.setParam(opts, PROXY_OPTIONS, proxyOptions);
573     }
574 
575     /**
576      * Sets the proxy password to use for the SFTP connection.
577      *
578      * @param opts
579      *            The FileSystem options.
580      * @param proxyPassword
581      *            the username used to connect to the proxy
582      * @see #getProxyPassword
583      * @since 2.1
584      */
585     public void setProxyPassword(final FileSystemOptions opts, final String proxyPassword)
586     {
587         this.setParam(opts, PROXY_PASSWORD, proxyPassword);
588     }
589 
590     /**
591      * Sets the proxy port to use for the SFTP connection.
592      * <p>
593      * You MUST also set the proxy host to use the proxy.
594      *
595      * @param opts
596      *            The FileSystem options.
597      * @param proxyPort
598      *            the port
599      * @see #setProxyHost
600      */
601     public void setProxyPort(final FileSystemOptions opts, final int proxyPort)
602     {
603         this.setParam(opts, PROXY_PORT, Integer.valueOf(proxyPort));
604     }
605 
606     /**
607      * Sets the proxy type to use for the SFTP connection.
608      *
609      * The possibles values are:
610      * <ul>
611      * <li>{@linkplain #PROXY_HTTP} connects using an HTTP proxy</li>
612      * <li>{@linkplain #PROXY_SOCKS5} connects using an Socket5 proxy</li>
613      * <li>{@linkplain #PROXY_STREAM} connects through a remote host stream command</li>
614      * </ul>
615      *
616      * @param opts
617      *            The FileSystem options.
618      * @param proxyType
619      *            the type of the proxy to use.
620      */
621     public void setProxyType(final FileSystemOptions opts, final ProxyType proxyType)
622     {
623         this.setParam(opts, PROXY_TYPE, proxyType);
624     }
625 
626     /**
627      * Sets the proxy username to use for the SFTP connection.
628      *
629      * @param opts
630      *            The FileSystem options.
631      * @param proxyUser
632      *            the username used to connect to the proxy
633      * @see #getProxyUser
634      * @since 2.1
635      */
636     public void setProxyUser(final FileSystemOptions opts, final String proxyUser)
637     {
638         this.setParam(opts, PROXY_USER, proxyUser);
639     }
640 
641     /**
642      * Configures the host key checking to use.
643      * <p>
644      * Valid arguments are: {@code "yes"}, {@code "no"} and {@code "ask"}.
645      * </p>
646      * <p>
647      * See the jsch documentation for details.
648      * </p>
649      *
650      * @param opts
651      *            The FileSystem options.
652      * @param hostKeyChecking
653      *            The host key checking to use.
654      * @throws FileSystemException
655      *             if an error occurs.
656      */
657     public void setStrictHostKeyChecking(final FileSystemOptions opts, final String hostKeyChecking)
658             throws FileSystemException
659     {
660         if (hostKeyChecking == null
661                 || (!hostKeyChecking.equals(HOST_KEY_CHECK_ASK) && !hostKeyChecking.equals(HOST_KEY_CHECK_NO) &&
662                     !hostKeyChecking.equals(HOST_KEY_CHECK_YES)))
663         {
664             throw new FileSystemException("vfs.provider.sftp/StrictHostKeyChecking-arg.error", hostKeyChecking);
665         }
666 
667         this.setParam(opts, STRICT_HOST_KEY_CHECKING, hostKeyChecking);
668     }
669 
670     /**
671      * Sets the timeout value on Jsch session.
672      *
673      * @param opts
674      *            The FileSystem options.
675      * @param timeout
676      *            The timeout in milliseconds.
677      */
678     public void setTimeout(final FileSystemOptions opts, final Integer timeout)
679     {
680         this.setParam(opts, TIMEOUT, timeout);
681     }
682 
683     /**
684      * Sets the whether to use the user directory as root (do not change to file system root).
685      *
686      * @param opts
687      *            The FileSystem options.
688      * @param userDirIsRoot
689      *            true if the user directory is the root directory.
690      */
691     public void setUserDirIsRoot(final FileSystemOptions opts, final boolean userDirIsRoot)
692     {
693         this.setParam(opts, USER_DIR_IS_ROOT, userDirIsRoot ? Boolean.TRUE : Boolean.FALSE);
694     }
695 
696     /**
697      * Sets the Jsch UserInfo class to use.
698      *
699      * @param opts
700      *            The FileSystem options.
701      * @param info
702      *            User information.
703      */
704     public void setUserInfo(final FileSystemOptions opts, final UserInfo info)
705     {
706         this.setParam(opts, UserInfo.class.getName(), info);
707     }
708 }