1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.provider.http4;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.ProxySelector;
22 import java.security.KeyManagementException;
23 import java.security.KeyStoreException;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.cert.CertificateException;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.stream.Stream;
32
33 import javax.net.ssl.HostnameVerifier;
34 import javax.net.ssl.SSLContext;
35
36 import org.apache.commons.lang3.StringUtils;
37 import org.apache.commons.lang3.time.DurationUtils;
38 import org.apache.commons.vfs2.Capability;
39 import org.apache.commons.vfs2.FileName;
40 import org.apache.commons.vfs2.FileSystem;
41 import org.apache.commons.vfs2.FileSystemConfigBuilder;
42 import org.apache.commons.vfs2.FileSystemException;
43 import org.apache.commons.vfs2.FileSystemOptions;
44 import org.apache.commons.vfs2.UserAuthenticationData;
45 import org.apache.commons.vfs2.UserAuthenticator;
46 import org.apache.commons.vfs2.provider.AbstractOriginatingFileProvider;
47 import org.apache.commons.vfs2.provider.GenericFileName;
48 import org.apache.commons.vfs2.util.UserAuthenticatorUtils;
49 import org.apache.http.ConnectionReuseStrategy;
50 import org.apache.http.Header;
51 import org.apache.http.HttpHost;
52 import org.apache.http.auth.AuthScope;
53 import org.apache.http.auth.UsernamePasswordCredentials;
54 import org.apache.http.client.AuthCache;
55 import org.apache.http.client.CookieStore;
56 import org.apache.http.client.CredentialsProvider;
57 import org.apache.http.client.HttpClient;
58 import org.apache.http.client.config.RequestConfig;
59 import org.apache.http.client.protocol.HttpClientContext;
60 import org.apache.http.config.Registry;
61 import org.apache.http.config.RegistryBuilder;
62 import org.apache.http.config.SocketConfig;
63 import org.apache.http.conn.HttpClientConnectionManager;
64 import org.apache.http.conn.routing.HttpRoutePlanner;
65 import org.apache.http.conn.socket.ConnectionSocketFactory;
66 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
67 import org.apache.http.conn.ssl.DefaultHostnameVerifier;
68 import org.apache.http.conn.ssl.NoopHostnameVerifier;
69 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
70 import org.apache.http.conn.ssl.TrustAllStrategy;
71 import org.apache.http.cookie.Cookie;
72 import org.apache.http.impl.DefaultConnectionReuseStrategy;
73 import org.apache.http.impl.NoConnectionReuseStrategy;
74 import org.apache.http.impl.auth.BasicScheme;
75 import org.apache.http.impl.client.BasicAuthCache;
76 import org.apache.http.impl.client.BasicCookieStore;
77 import org.apache.http.impl.client.BasicCredentialsProvider;
78 import org.apache.http.impl.client.HttpClientBuilder;
79 import org.apache.http.impl.client.HttpClients;
80 import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
81 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
82 import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
83 import org.apache.http.message.BasicHeader;
84 import org.apache.http.protocol.HTTP;
85 import org.apache.http.ssl.SSLContextBuilder;
86
87
88
89
90
91
92
93 @Deprecated
94 public class Http4FileProvider extends AbstractOriginatingFileProvider {
95
96
97 static final UserAuthenticationData.Type[] AUTHENTICATOR_TYPES =
98 {
99 UserAuthenticationData.USERNAME,
100 UserAuthenticationData.PASSWORD
101 };
102
103
104 static final Collection<Capability> CAPABILITIES =
105 Collections.unmodifiableCollection(
106 Arrays.asList(
107 Capability.GET_TYPE,
108 Capability.READ_CONTENT,
109 Capability.URI,
110 Capability.GET_LAST_MODIFIED,
111 Capability.ATTRIBUTES,
112 Capability.RANDOM_ACCESS_READ,
113 Capability.DIRECTORY_READ_CONTENT
114 )
115 );
116
117
118
119
120 public Http4FileProvider() {
121 setFileNameParser(Http4FileNameParser.getInstance());
122 }
123
124 private HttpClientConnectionManager createConnectionManager(final Http4FileSystemConfigBuilder builder,
125 final FileSystemOptions fileSystemOptions, final SSLContext sslContext, final HostnameVerifier verifier) {
126 final SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext, verifier);
127
128 final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
129 .register("https", sslFactory)
130 .register("http", new PlainConnectionSocketFactory())
131 .build();
132
133
134 final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
135 connManager.setMaxTotal(builder.getMaxTotalConnections(fileSystemOptions));
136 connManager.setDefaultMaxPerRoute(builder.getMaxConnectionsPerHost(fileSystemOptions));
137
138
139 final SocketConfig socketConfig = SocketConfig
140 .custom()
141 .setSoTimeout(DurationUtils.toMillisInt(builder.getSoTimeoutDuration(fileSystemOptions)))
142 .build();
143
144
145 connManager.setDefaultSocketConfig(socketConfig);
146
147 return connManager;
148 }
149
150 private CookieStore createDefaultCookieStore(final Http4FileSystemConfigBuilder builder,
151 final FileSystemOptions fileSystemOptions) {
152 final CookieStore cookieStore = new BasicCookieStore();
153 final Cookie[] cookies = builder.getCookies(fileSystemOptions);
154
155 if (cookies != null) {
156 Stream.of(cookies).forEach(cookieStore::addCookie);
157 }
158
159 return cookieStore;
160 }
161
162 private RequestConfig createDefaultRequestConfig(final Http4FileSystemConfigBuilder builder,
163 final FileSystemOptions fileSystemOptions) {
164 return RequestConfig.custom()
165 .setConnectTimeout(DurationUtils.toMillisInt(builder.getConnectionTimeoutDuration(fileSystemOptions)))
166 .build();
167 }
168
169 private HostnameVerifier createHostnameVerifier(final Http4FileSystemConfigBuilder builder,
170 final FileSystemOptions fileSystemOptions) {
171 return builder.isHostnameVerificationEnabled(fileSystemOptions) ? new DefaultHostnameVerifier()
172 : NoopHostnameVerifier.INSTANCE;
173 }
174
175
176
177
178
179
180
181
182
183
184 protected HttpClient createHttpClient(final Http4FileSystemConfigBuilder builder, final GenericFileName rootName,
185 final FileSystemOptions fileSystemOptions) throws FileSystemException {
186 return createHttpClientBuilder(builder, rootName, fileSystemOptions).build();
187 }
188
189
190
191
192
193
194
195
196
197
198 protected HttpClientBuilder createHttpClientBuilder(final Http4FileSystemConfigBuilder builder, final GenericFileName rootName,
199 final FileSystemOptions fileSystemOptions) throws FileSystemException {
200 final List<Header> defaultHeaders = new ArrayList<>();
201 defaultHeaders.add(new BasicHeader(HTTP.USER_AGENT, builder.getUserAgent(fileSystemOptions)));
202
203 final ConnectionReuseStrategy connectionReuseStrategy = builder.isKeepAlive(fileSystemOptions)
204 ? DefaultConnectionReuseStrategy.INSTANCE
205 : NoConnectionReuseStrategy.INSTANCE;
206 final SSLContext sslContext = createSSLContext(builder, fileSystemOptions);
207 final HostnameVerifier hostNameVerifier = createHostnameVerifier(builder, fileSystemOptions);
208 final HttpClientBuilder httpClientBuilder =
209 HttpClients.custom()
210 .setRoutePlanner(createHttpRoutePlanner(builder, fileSystemOptions))
211 .setConnectionManager(createConnectionManager(builder, fileSystemOptions, sslContext, hostNameVerifier))
212 .setSSLContext(sslContext)
213 .setSSLHostnameVerifier(hostNameVerifier)
214 .setConnectionReuseStrategy(connectionReuseStrategy)
215 .setDefaultRequestConfig(createDefaultRequestConfig(builder, fileSystemOptions))
216 .setDefaultHeaders(defaultHeaders)
217 .setDefaultCookieStore(createDefaultCookieStore(builder, fileSystemOptions));
218
219 if (!builder.getFollowRedirect(fileSystemOptions)) {
220 httpClientBuilder.disableRedirectHandling();
221 }
222
223 return httpClientBuilder;
224 }
225
226
227
228
229
230
231
232
233
234
235 protected HttpClientContext createHttpClientContext(final Http4FileSystemConfigBuilder builder,
236 final GenericFileName rootName, final FileSystemOptions fileSystemOptions,
237 final UserAuthenticationData authData) {
238
239 final HttpClientContext clientContext = HttpClientContext.create();
240 final CredentialsProvider credsProvider = new BasicCredentialsProvider();
241 clientContext.setCredentialsProvider(credsProvider);
242
243 final String username = UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
244 UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(rootName.getUserName())));
245 final String password = UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
246 UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(rootName.getPassword())));
247
248 if (!StringUtils.isEmpty(username)) {
249 credsProvider.setCredentials(new AuthScope(rootName.getHostName(), rootName.getPort()),
250 new UsernamePasswordCredentials(username, password));
251 }
252
253 final HttpHost proxyHost = getProxyHttpHost(builder, fileSystemOptions);
254
255 if (proxyHost != null) {
256 final UserAuthenticator proxyAuth = builder.getProxyAuthenticator(fileSystemOptions);
257
258 if (proxyAuth != null) {
259 final UserAuthenticationData proxyAuthData = UserAuthenticatorUtils.authenticate(proxyAuth,
260 new UserAuthenticationData.Type[] {UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD});
261
262 if (proxyAuthData != null) {
263 final UsernamePasswordCredentials proxyCreds = new UsernamePasswordCredentials(
264 UserAuthenticatorUtils.toString(
265 UserAuthenticatorUtils.getData(proxyAuthData, UserAuthenticationData.USERNAME, null)),
266 UserAuthenticatorUtils.toString(
267 UserAuthenticatorUtils.getData(proxyAuthData, UserAuthenticationData.PASSWORD, null)));
268
269 credsProvider.setCredentials(new AuthScope(proxyHost.getHostName(), proxyHost.getPort()),
270 proxyCreds);
271 }
272
273 if (builder.isPreemptiveAuth(fileSystemOptions)) {
274 final AuthCache authCache = new BasicAuthCache();
275 final BasicScheme basicAuth = new BasicScheme();
276 authCache.put(proxyHost, basicAuth);
277 clientContext.setAuthCache(authCache);
278 }
279 }
280 }
281
282 return clientContext;
283 }
284
285 private HttpRoutePlanner createHttpRoutePlanner(final Http4FileSystemConfigBuilder builder,
286 final FileSystemOptions fileSystemOptions) {
287 final HttpHost proxyHost = getProxyHttpHost(builder, fileSystemOptions);
288
289 if (proxyHost != null) {
290 return new DefaultProxyRoutePlanner(proxyHost);
291 }
292
293 return new SystemDefaultRoutePlanner(ProxySelector.getDefault());
294 }
295
296
297
298
299
300
301
302
303
304 protected SSLContext createSSLContext(final Http4FileSystemConfigBuilder builder,
305 final FileSystemOptions fileSystemOptions) throws FileSystemException {
306 try {
307 final SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
308 sslContextBuilder.setKeyStoreType(builder.getKeyStoreType(fileSystemOptions));
309
310 File keystoreFileObject = null;
311 final String keystoreFile = builder.getKeyStoreFile(fileSystemOptions);
312
313 if (!StringUtils.isEmpty(keystoreFile)) {
314 keystoreFileObject = new File(keystoreFile);
315 }
316
317 if (keystoreFileObject != null && keystoreFileObject.exists()) {
318 final String keystorePass = builder.getKeyStorePass(fileSystemOptions);
319 final char[] keystorePassChars = keystorePass != null ? keystorePass.toCharArray() : null;
320 sslContextBuilder.loadTrustMaterial(keystoreFileObject, keystorePassChars, TrustAllStrategy.INSTANCE);
321 } else {
322 sslContextBuilder.loadTrustMaterial(TrustAllStrategy.INSTANCE);
323 }
324
325 return sslContextBuilder.build();
326 } catch (final KeyStoreException e) {
327 throw new FileSystemException("Keystore error. " + e.getMessage(), e);
328 } catch (final KeyManagementException e) {
329 throw new FileSystemException("Cannot retrieve keys. " + e.getMessage(), e);
330 } catch (final NoSuchAlgorithmException e) {
331 throw new FileSystemException("Algorithm error. " + e.getMessage(), e);
332 } catch (final CertificateException e) {
333 throw new FileSystemException("Certificate error. " + e.getMessage(), e);
334 } catch (final IOException e) {
335 throw new FileSystemException("Cannot open key file. " + e.getMessage(), e);
336 }
337 }
338
339 @Override
340 protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
341 throws FileSystemException {
342 final GenericFileName rootName = (GenericFileName) name;
343 UserAuthenticationData authData = null;
344 HttpClient httpClient;
345 HttpClientContext httpClientContext;
346 try {
347 final Http4FileSystemConfigBuilder builder = Http4FileSystemConfigBuilder.getInstance();
348 authData = UserAuthenticatorUtils.authenticate(fileSystemOptions, AUTHENTICATOR_TYPES);
349 httpClientContext = createHttpClientContext(builder, rootName, fileSystemOptions, authData);
350 httpClient = createHttpClient(builder, rootName, fileSystemOptions);
351 } finally {
352 UserAuthenticatorUtils.cleanup(authData);
353 }
354 return new Http4FileSystem(rootName, fileSystemOptions, httpClient, httpClientContext);
355 }
356
357 @Override
358 public Collection<Capability> getCapabilities() {
359 return CAPABILITIES;
360 }
361
362 @Override
363 public FileSystemConfigBuilder getConfigBuilder() {
364 return Http4FileSystemConfigBuilder.getInstance();
365 }
366
367 private HttpHost getProxyHttpHost(final Http4FileSystemConfigBuilder builder,
368 final FileSystemOptions fileSystemOptions) {
369 final String proxyHost = builder.getProxyHost(fileSystemOptions);
370 final int proxyPort = builder.getProxyPort(fileSystemOptions);
371 final String proxyScheme = builder.getProxyScheme(fileSystemOptions);
372
373 if (!StringUtils.isEmpty(proxyHost) && proxyPort > 0) {
374 return new HttpHost(proxyHost, proxyPort, proxyScheme);
375 }
376
377 return null;
378 }
379
380 }