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.http5;
018
019import java.security.KeyStore;
020import java.time.Duration;
021
022import org.apache.commons.vfs2.FileSystem;
023import org.apache.commons.vfs2.FileSystemConfigBuilder;
024import org.apache.commons.vfs2.FileSystemOptions;
025import org.apache.commons.vfs2.UserAuthenticator;
026import org.apache.hc.client5.http.cookie.Cookie;
027import org.apache.hc.core5.http.HttpHost;
028
029/**
030 * Configuration options builder utility for http5 provider.
031 *
032 * @since 2.5.0
033 */
034public class Http5FileSystemConfigBuilder extends FileSystemConfigBuilder {
035
036    /**
037     * Defines whether the HttpClient should follow redirections from the responses.
038     * <p>
039     * This parameter expects a value of type {@link Boolean}.
040     * </p>
041     */
042    protected static final String KEY_FOLLOW_REDIRECT = "followRedirect";
043
044    private static final Http5FileSystemConfigBuilder BUILDER = new Http5FileSystemConfigBuilder();
045
046    /**
047     * Defines the maximum number of connections allowed overall. This value only applies
048     * to the number of connections from a particular instance of HTTP connection manager.
049     * <p>
050     * This parameter expects a value of type {@link Integer}.
051     * </p>
052     */
053    private static final String MAX_TOTAL_CONNECTIONS = "http.connection-manager.max-total";
054
055    /**
056     * Defines the maximum number of connections allowed per host configuration.
057     * These values only apply to the number of connections from a particular instance
058     * of HTTP connection manager.
059     */
060    private static final String MAX_HOST_CONNECTIONS = "http.connection-manager.max-per-host";
061
062    /**
063     * Defines the connection timeout of an HTTP request.
064     * <p>
065     * This parameter expects a value of type {@link Integer}.
066     * </p>
067     */
068    private static final String CONNECTION_TIMEOUT = "http.connection.timeout";
069
070    /**
071     * Defines the socket timeout of an HTTP request.
072     * <p>
073     * This parameter expects a value of type {@link Integer}.
074     * </p>
075     */
076    private static final String SO_TIMEOUT = "http.socket.timeout";
077
078    /**
079     * Defines whether Keep-Alive option is used or not.
080     * <p>
081     * This parameter expects a value of type {@link Boolean}.
082     * </p>
083     */
084    private static final String KEEP_ALIVE = "http.keepAlive";
085
086    /**
087     * Defines the keystore file path for SSL connections.
088     * <p>
089     * This parameter expects a value of type {@link String}.
090     * </p>
091     */
092    private static final String KEYSTORE_FILE = "http.keystoreFile";
093
094    /**
095     * Defines the keystore pass phrase for SSL connections.
096     * <p>
097     * This parameter expects a value of type {@link String}.
098     * </p>
099     */
100    private static final String KEYSTORE_PASS = "http.keystorePass";
101
102    /**
103     * Defines the keystore type for the underlying HttpClient.
104     */
105    private static final String KEYSTORE_TYPE = "http.keyStoreType";
106
107    /**
108     * Defines whether the host name should be verified or not in SSL connections.
109     * <p>
110     * This parameter expects a value of type {@link Boolean}.
111     * </p>
112     */
113    private static final String HOSTNAME_VERIFICATION_ENABLED = "http.hostname-verification.enabled";
114
115    /**
116     * Defines the charset of a URL.
117     */
118    private static final String KEY_URL_CHARSET = "urlCharset";
119
120    /**
121     * Defines the User-Agent request header string of the underlying HttpClient.
122     * <p>
123     * This parameter expects a value of type {@link String}.
124     * </p>
125     */
126    private static final String KEY_USER_AGENT = "userAgent";
127
128    /**
129     * Defines http scheme for proxy host
130     *<p>
131     *This parameter expects a value of type {@link String}.
132     *</p>
133     */
134    private static final String PROXY_SCHEME = "proxyScheme";
135
136    /**
137     * Defines whether the preemptive authentication should be enabled or not.
138     * <p>
139     * This parameter expects a value of type {@link Boolean}.
140     * </p>
141     */
142    private static final String KEY_PREEMPTIVE_AUTHENTICATION = "preemptiveAuth";
143
144    /**
145     * Defines the enabled TLS versions for the underlying HttpClient.
146     * <p>
147     * This parameter expects a value of type {@link String} as a comma separated string, each token of
148     * which is the name of {@code org.apache.hc.core5.http.ssl.TLS} enum. e.g, "V_1_2, V_1_3".
149     * </p>
150     */
151    private static final String KEY_TLS_VERSIONS = "tlsVersions";
152
153    /**
154     * The default value for {@link #MAX_TOTAL_CONNECTIONS} configuration.
155     */
156    private static final int DEFAULT_MAX_CONNECTIONS = 50;
157
158    /**
159     * The default value for {@link #MAX_HOST_CONNECTIONS} configuration.
160     */
161    private static final int DEFAULT_MAX_HOST_CONNECTIONS = 5;
162
163    /**
164     * The default value for {@link #CONNECTION_TIMEOUT} configuration.
165     */
166    private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ZERO;
167
168    /**
169     * The default value for {@link #SO_TIMEOUT} configuration.
170     */
171    private static final Duration DEFAULT_SO_TIMEOUT = Duration.ZERO;
172
173    /**
174     * The default value for {@link #KEEP_ALIVE} configuration.
175     */
176    private static final boolean DEFAULT_KEEP_ALIVE = true;
177
178    /**
179     * The default value for {@link #KEY_FOLLOW_REDIRECT} configuration.
180     */
181    private static final boolean DEFAULT_FOLLOW_REDIRECT = true;
182
183    /**
184     * The default value for {@link #KEY_USER_AGENT} configuration.
185     */
186    private static final String DEFAULT_USER_AGENT = "Jakarta-Commons-VFS";
187
188    /**
189     * The default value for {@link #HOSTNAME_VERIFICATION_ENABLED} configuration.
190     */
191    private static final boolean DEFAULT_HOSTNAME_VERIFICATION_ENABLED = true;
192
193    /**
194     * The default value for {@link #KEY_TLS_VERSIONS} configuration as a comma separated string, each token of
195     * which is the name of {@code org.apache.hc.core5.http.ssl.TLS} enum. e.g, "V_1_2, V_1_3".
196     */
197    private static final String DEFAULT_TLS_VERSIONS = "V_1_2";
198
199    /**
200     * Gets the singleton builder.
201     *
202     * @return the singleton builder.
203     */
204    public static Http5FileSystemConfigBuilder getInstance() {
205        return BUILDER;
206    }
207
208    private Http5FileSystemConfigBuilder() {
209        super("http.");
210    }
211
212    /**
213     * Constructs an {@code Http4FileSystemConfigBuilder}.
214     *
215     * @param prefix String for properties of this file system.
216     */
217    protected Http5FileSystemConfigBuilder(final String prefix) {
218        super(prefix);
219    }
220
221    @Override
222    protected Class<? extends FileSystem> getConfigClass() {
223        return Http5FileSystem.class;
224    }
225
226    /**
227     * Gets the connection timeout.
228     *
229     * @param opts The FileSystem options.
230     * @return The connection timeout.
231     * @deprecated {@link #getConnectionTimeoutDuration(FileSystemOptions)}.
232     */
233    @Deprecated
234    public int getConnectionTimeout(final FileSystemOptions opts) {
235        return getDurationInteger(opts, CONNECTION_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
236    }
237
238    /**
239     * Gets the connection timeout.
240     *
241     * @param opts The FileSystem options.
242     * @return The connection timeout.
243     * @since 2.8.0
244     */
245    public Duration getConnectionTimeoutDuration(final FileSystemOptions opts) {
246        return getDuration(opts, CONNECTION_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
247    }
248
249    /**
250     * Gets the cookies to add to the request.
251     *
252     * @param opts The FileSystem options.
253     * @return the Cookie array.
254     */
255    public Cookie[] getCookies(final FileSystemOptions opts) {
256        return getParam(opts, "cookies");
257    }
258
259    /**
260     * Gets whether to follow redirects for the connection.
261     *
262     * @param opts The FileSystem options.
263     * @return {@code true} to follow redirects, {@code false} not to.
264     * @see #setFollowRedirect
265     */
266    public boolean getFollowRedirect(final FileSystemOptions opts) {
267        return getBoolean(opts, KEY_FOLLOW_REDIRECT, DEFAULT_FOLLOW_REDIRECT);
268    }
269
270    /**
271     * Gets keystore file path to be used in SSL connections.
272     * @param opts the file system options to modify
273     * @return keystore file path to be used in SSL connections
274     */
275    public String getKeyStoreFile(final FileSystemOptions opts) {
276        return getParam(opts, KEYSTORE_FILE);
277    }
278
279    /**
280     * Gets keystore pass phrase for SSL connections.
281     * @param opts the file system options to modify
282     * @return keystore pass phrase for SSL connections
283     */
284    String getKeyStorePass(final FileSystemOptions opts) {
285        return getParam(opts, KEYSTORE_PASS);
286    }
287
288    /**
289     * Gets keystore type for SSL connections.
290     * @param opts the file system options to modify
291     * @return keystore type for SSL connections
292     * @since 2.7.0
293     */
294    public String getKeyStoreType(final FileSystemOptions opts) {
295        return getString(opts, KEYSTORE_TYPE, KeyStore.getDefaultType());
296    }
297
298    /**
299     * Gets the maximum number of connections allowed per host.
300     *
301     * @param opts The FileSystemOptions.
302     * @return The maximum number of connections allowed per host.
303     */
304    public int getMaxConnectionsPerHost(final FileSystemOptions opts) {
305        return getInteger(opts, MAX_HOST_CONNECTIONS, DEFAULT_MAX_HOST_CONNECTIONS);
306    }
307
308    /**
309     * Gets the maximum number of connections allowed.
310     *
311     * @param opts The FileSystemOptions.
312     * @return The maximum number of connections allowed.
313     */
314    public int getMaxTotalConnections(final FileSystemOptions opts) {
315        return getInteger(opts, MAX_TOTAL_CONNECTIONS, DEFAULT_MAX_CONNECTIONS);
316    }
317
318    /**
319     * Gets the proxy authenticator where the system should get the credentials from.
320     *
321     * @param opts The FileSystem options.
322     * @return The UserAuthenticator.
323     */
324    public UserAuthenticator getProxyAuthenticator(final FileSystemOptions opts) {
325        return getParam(opts, "proxyAuthenticator");
326    }
327
328    /**
329     * Gets the proxy to use for http connection. You have to set the ProxyPort too if you would like to have the proxy
330     * really used.
331     *
332     * @param opts The FileSystem options.
333     * @return proxyHost
334     * @see #setProxyPort
335     */
336    public String getProxyHost(final FileSystemOptions opts) {
337        return getString(opts, "proxyHost");
338    }
339
340    /**
341     * Gets the proxy-port to use for http the connection. You have to set the ProxyHost too if you would like to have
342     * the proxy really used.
343     *
344     * @param opts The FileSystem options.
345     * @return proxyPort: the port number or 0 if it is not set
346     * @see #setProxyHost
347     */
348    public int getProxyPort(final FileSystemOptions opts) {
349        return getInteger(opts, "proxyPort", 0);
350    }
351
352    /**
353     * Gets the proxy-scheme to use for http the connection. You have to set the ProxyHost too if you would like to have
354     * the proxy really used.
355     *
356     * @param opts The FileSystem options.
357     * @return proxyScheme: the http/https scheme of proxy server
358     * @see #setProxyHost
359     * @since 2.7.0
360     */
361    public String getProxyScheme(final FileSystemOptions opts) {
362        return getString(opts, PROXY_SCHEME, HttpHost.DEFAULT_SCHEME.getId());
363    }
364
365    /**
366     * Gets the socket timeout.
367     *
368     * @param opts The FileSystemOptions.
369     * @return The socket timeout.
370     * @deprecated Use {@link #getSoTimeoutDuration(FileSystemOptions)}.
371     */
372    @Deprecated
373    public int getSoTimeout(final FileSystemOptions opts) {
374        return getDurationInteger(opts, SO_TIMEOUT, DEFAULT_SO_TIMEOUT);
375    }
376
377    /**
378     * Gets the socket timeout.
379     *
380     * @param opts The FileSystemOptions.
381     * @return The socket timeout.
382     * @since 2.8.0
383     */
384    public Duration getSoTimeoutDuration(final FileSystemOptions opts) {
385        return getDuration(opts, SO_TIMEOUT, DEFAULT_SO_TIMEOUT);
386    }
387
388    /**
389     * Gets the enabled TLS versions as a comma separated string, each token of which is the name of
390     * {@code org.apache.hc.core5.http.ssl.TLS} enum. e.g, "V_1_2, V_1_3".
391     *
392     * @param opts the file system options to modify
393     * @return enabled TLS versions
394     */
395    public String getTlsVersions(final FileSystemOptions opts) {
396        final String tlsVersions = getParam(opts, KEY_TLS_VERSIONS);
397        return tlsVersions != null ? tlsVersions : DEFAULT_TLS_VERSIONS;
398    }
399
400    /**
401     * Gets the charset used for url encoding.
402     *
403     * @param opts The FileSystem options.
404     * @return the charset name
405     */
406    public String getUrlCharset(final FileSystemOptions opts) {
407        return getString(opts, KEY_URL_CHARSET);
408    }
409
410    /**
411     * Gets the user agent string.
412     *
413     * @param opts the file system options to modify
414     * @return User provided User-Agent string, otherwise default of: Commons-VFS
415     */
416    public String getUserAgent(final FileSystemOptions opts) {
417        final String userAgent = getParam(opts, KEY_USER_AGENT);
418        return userAgent != null ? userAgent : DEFAULT_USER_AGENT;
419    }
420
421    /**
422     * Determines if the hostname should be verified in SSL context.
423     *
424     * @param opts The FileSystemOptions.
425     * @return true if the FileSystemOptions indicate that HTTP Keep-Alive is respected.
426     */
427    public boolean isHostnameVerificationEnabled(final FileSystemOptions opts) {
428        return getBoolean(opts, HOSTNAME_VERIFICATION_ENABLED, DEFAULT_HOSTNAME_VERIFICATION_ENABLED);
429    }
430
431    /**
432     * Determines if the FileSystemOptions indicate that HTTP Keep-Alive is respected.
433     *
434     * @param opts The FileSystemOptions.
435     * @return true if the FileSystemOptions indicate that HTTP Keep-Alive is respected.
436     */
437    public boolean isKeepAlive(final FileSystemOptions opts) {
438        return getBoolean(opts, KEEP_ALIVE, DEFAULT_KEEP_ALIVE);
439    }
440
441    /**
442     * Determines if the FileSystemOptions indicate that preemptive authentication is requested.
443     *
444     * @param opts The FileSystemOptions.
445     * @return true if preemptiveAuth is requested.
446     */
447    public boolean isPreemptiveAuth(final FileSystemOptions opts) {
448        return getBoolean(opts, KEY_PREEMPTIVE_AUTHENTICATION, Boolean.FALSE).booleanValue();
449    }
450
451    /**
452     * Sets the connection timeout.
453     *
454     * @param opts The FileSystem options.
455     * @param connectionTimeout The connection timeout.
456     * @since 2.8.0
457     */
458    public void setConnectionTimeout(final FileSystemOptions opts, final Duration connectionTimeout) {
459        setParam(opts, CONNECTION_TIMEOUT, connectionTimeout);
460    }
461
462    /**
463     * Sets the connection timeout.
464     *
465     * @param opts The FileSystem options.
466     * @param connectionTimeout The connection timeout.
467     * @deprecated Use {@link #setConnectionTimeout(FileSystemOptions, Duration)}.
468     */
469    @Deprecated
470    public void setConnectionTimeout(final FileSystemOptions opts, final int connectionTimeout) {
471        setConnectionTimeout(opts, Duration.ofMillis(connectionTimeout));
472    }
473
474    /**
475     * The cookies to add to the request.
476     *
477     * @param opts The FileSystem options.
478     * @param cookies An array of Cookies.
479     */
480    public void setCookies(final FileSystemOptions opts, final Cookie[] cookies) {
481        setParam(opts, "cookies", cookies);
482    }
483
484    /**
485     * Sets whether to follow redirects for the connection.
486     *
487     * @param opts The FileSystem options.
488     * @param redirect {@code true} to follow redirects, {@code false} not to.
489     * @see #setFollowRedirect
490     */
491    public void setFollowRedirect(final FileSystemOptions opts, final boolean redirect) {
492        setParam(opts, KEY_FOLLOW_REDIRECT, redirect);
493    }
494
495    /**
496     * Sets if the hostname should be verified in SSL context.
497     *
498     * @param opts The FileSystemOptions.
499     * @param hostnameVerificationEnabled whether hostname should be verified
500     */
501    public void setHostnameVerificationEnabled(final FileSystemOptions opts, final boolean hostnameVerificationEnabled) {
502        setParam(opts, HOSTNAME_VERIFICATION_ENABLED, Boolean.valueOf(hostnameVerificationEnabled));
503    }
504
505    /**
506     * Sets if the FileSystemOptions indicate that HTTP Keep-Alive is respected.
507     *
508     * @param opts The FileSystemOptions.
509     * @param keepAlive whether the FileSystemOptions indicate that HTTP Keep-Alive is respected or not.
510     */
511    public void setKeepAlive(final FileSystemOptions opts, final boolean keepAlive) {
512        setParam(opts, KEEP_ALIVE, Boolean.valueOf(keepAlive));
513    }
514
515    /**
516     * Sets keystore file path for SSL connections.
517     * @param opts the file system options to modify
518     * @param keyStoreFile keystore file path
519     */
520    public void setKeyStoreFile(final FileSystemOptions opts, final String keyStoreFile) {
521        setParam(opts, KEYSTORE_FILE, keyStoreFile);
522    }
523
524    /**
525     * Sets keystore pass phrase for SSL connections.
526     * @param opts the file system options to modify
527     * @param keyStorePass keystore pass phrase for SSL connections
528     */
529    public void setKeyStorePass(final FileSystemOptions opts, final String keyStorePass) {
530        setParam(opts, KEYSTORE_PASS, keyStorePass);
531    }
532
533    /**
534     * Sets keystore type for SSL connections.
535     * @param opts the file system options to modify
536     * @param keyStoreType keystore type for SSL connections
537     * @since 2.7.0
538     */
539    public void setKeyStoreType(final FileSystemOptions opts, final String keyStoreType) {
540        setParam(opts, KEYSTORE_TYPE, keyStoreType);
541    }
542
543    /**
544     * Sets the maximum number of connections allowed to any host.
545     *
546     * @param opts The FileSystem options.
547     * @param maxHostConnections The maximum number of connections to a host.
548     */
549    public void setMaxConnectionsPerHost(final FileSystemOptions opts, final int maxHostConnections) {
550        setParam(opts, MAX_HOST_CONNECTIONS, Integer.valueOf(maxHostConnections));
551    }
552
553    /**
554     * Sets the maximum number of connections allowed.
555     *
556     * @param opts The FileSystem options.
557     * @param maxTotalConnections The maximum number of connections.
558     */
559    public void setMaxTotalConnections(final FileSystemOptions opts, final int maxTotalConnections) {
560        setParam(opts, MAX_TOTAL_CONNECTIONS, Integer.valueOf(maxTotalConnections));
561    }
562
563    /**
564     * Sets the given value for preemptive HTTP authentication (using BASIC) on the given FileSystemOptions object.
565     * Defaults to false if not set. It may be appropriate to set to true in cases when the resulting chattiness of the
566     * conversation outweighs any architectural desire to use a stronger authentication scheme than basic/preemptive.
567     *
568     * @param opts The FileSystemOptions.
569     * @param preemptiveAuth the desired setting; true=enabled and false=disabled.
570     */
571    public void setPreemptiveAuth(final FileSystemOptions opts, final boolean preemptiveAuth) {
572        setParam(opts, KEY_PREEMPTIVE_AUTHENTICATION, Boolean.valueOf(preemptiveAuth));
573    }
574
575    /**
576     * Sets the proxy authenticator where the system should get the credentials from.
577     *
578     * @param opts The FileSystem options.
579     * @param authenticator The UserAuthenticator.
580     */
581    public void setProxyAuthenticator(final FileSystemOptions opts, final UserAuthenticator authenticator) {
582        setParam(opts, "proxyAuthenticator", authenticator);
583    }
584
585    /**
586     * Sets the proxy to use for http connection.
587     * <p>
588     * You have to set the ProxyPort too if you would like to have the proxy really used.
589     * </p>
590     *
591     * @param opts The FileSystem options.
592     * @param proxyHost the host
593     * @see #setProxyPort
594     */
595    public void setProxyHost(final FileSystemOptions opts, final String proxyHost) {
596        setParam(opts, "proxyHost", proxyHost);
597    }
598
599    /**
600     * Sets the proxy-port to use for http connection. You have to set the ProxyHost too if you would like to have the
601     * proxy really used.
602     *
603     * @param opts The FileSystem options.
604     * @param proxyPort the port
605     * @see #setProxyHost
606     */
607    public void setProxyPort(final FileSystemOptions opts, final int proxyPort) {
608        setParam(opts, "proxyPort", Integer.valueOf(proxyPort));
609    }
610    /**
611     * Sets the proxy-scheme to use for http connection. You have to set the ProxyHost too if you would like to have the
612     * proxy really used.
613     *
614     * @param opts The FileSystem options.
615     * @param proxyScheme the protocol scheme
616     * @see #setProxyHost
617     * @since 2.7.0
618     */
619    public void setProxyScheme(final FileSystemOptions opts, final String proxyScheme) {
620        setParam(opts, PROXY_SCHEME, proxyScheme);
621    }
622
623    /**
624     * The socket timeout.
625     *
626     * @param opts The FileSystem options.
627     * @param soTimeout socket timeout.
628     */
629    public void setSoTimeout(final FileSystemOptions opts, final Duration soTimeout) {
630        setParam(opts, SO_TIMEOUT, soTimeout);
631    }
632
633    /**
634     * Sets the socket timeout.
635     *
636     * @param opts The FileSystem options.
637     * @param soTimeout socket timeout.
638     * @deprecated Use {@link #setSoTimeout(FileSystemOptions, Duration)}.
639     */
640    @Deprecated
641    public void setSoTimeout(final FileSystemOptions opts, final int soTimeout) {
642        setSoTimeout(opts, Duration.ofMillis(soTimeout));
643    }
644
645    /**
646     * Sets the enabled TLS versions as a comma separated string, each token of which is the name of
647     * {@code org.apache.hc.core5.http.ssl.TLS} enum. e.g, "V_1_2, V_1_3".
648     *
649     * @param opts the file system options to modify
650     * @param tlsVersions enabled TLS versions
651     */
652    public void setTlsVersions(final FileSystemOptions opts, final String tlsVersions) {
653        setParam(opts, KEY_TLS_VERSIONS, tlsVersions);
654    }
655
656    /**
657     * Sets the charset used for url encoding.
658     *
659     * @param opts The FileSystem options.
660     * @param charset the charset name.
661     */
662    public void setUrlCharset(final FileSystemOptions opts, final String charset) {
663        setParam(opts, KEY_URL_CHARSET, charset);
664    }
665
666    /**
667     * Sets the user agent to attach to the outgoing http methods.
668     *
669     * @param opts the file system options to modify
670     * @param userAgent User Agent String
671     */
672    public void setUserAgent(final FileSystemOptions opts, final String userAgent) {
673        setParam(opts, KEY_USER_AGENT, userAgent);
674    }
675}