Java tutorial
/* * Copyright (C) 2014 Guillaume Nodet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ops4j.pax.url.mvn.internal.wagon; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.auth.AUTH; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.auth.NTCredentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicHeader; import org.apache.http.protocol.HTTP; import org.apache.maven.wagon.ConnectionException; import org.apache.maven.wagon.authentication.AuthenticationException; import org.apache.maven.wagon.authentication.AuthenticationInfo; import org.apache.maven.wagon.providers.http.AbstractHttpClientWagon; import org.apache.maven.wagon.providers.http.HttpMethodConfiguration; import org.apache.maven.wagon.providers.http.HttpWagon; import org.apache.maven.wagon.proxy.ProxyInfo; import org.apache.maven.wagon.proxy.ProxyInfoProvider; import org.apache.maven.wagon.repository.Repository; import org.ops4j.net.URLUtils; /** * An http wagon provider providing more configuration options * through the use of an HttpClient instance. * * @author Guillaume Nodet */ public class ConfigurableHttpWagon extends HttpWagon { private final CloseableHttpClient client; public ConfigurableHttpWagon(CloseableHttpClient client, int readTimeout, int connectionTimeout) { this.client = client; setReadTimeout(readTimeout); setTimeout(connectionTimeout); } @Override protected CloseableHttpResponse execute(HttpUriRequest httpMethod) throws HttpException, IOException { setHeaders(httpMethod); String userAgent = getUserAgent(httpMethod); if (userAgent != null) { httpMethod.setHeader(HTTP.USER_AGENT, userAgent); } RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); // WAGON-273: default the cookie-policy to browser compatible requestConfigBuilder.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY); Repository repo = getRepository(); ProxyInfo proxyInfo = getProxyInfo(repo.getProtocol(), repo.getHost()); if (proxyInfo != null) { HttpHost proxy = new HttpHost(proxyInfo.getHost(), proxyInfo.getPort()); requestConfigBuilder.setProxy(proxy); } HttpMethodConfiguration config = getHttpConfiguration() == null ? null : getHttpConfiguration().getMethodConfiguration(httpMethod); if (config != null) { copyConfig(config, requestConfigBuilder); } else { requestConfigBuilder.setSocketTimeout(getReadTimeout()); requestConfigBuilder.setConnectTimeout(getTimeout()); } getLocalContext().setRequestConfig(requestConfigBuilder.build()); if (config != null && config.isUsePreemptive()) { HttpHost targetHost = new HttpHost(repo.getHost(), repo.getPort(), repo.getProtocol()); AuthScope targetScope = getBasicAuthScope().getScope(targetHost); if (getCredentialsProvider().getCredentials(targetScope) != null) { BasicScheme targetAuth = new BasicScheme(); targetAuth.processChallenge(new BasicHeader(AUTH.WWW_AUTH, "BASIC preemptive")); getAuthCache().put(targetHost, targetAuth); } } if (proxyInfo != null) { if (proxyInfo.getHost() != null) { HttpHost proxyHost = new HttpHost(proxyInfo.getHost(), proxyInfo.getPort()); AuthScope proxyScope = getProxyBasicAuthScope().getScope(proxyHost); String proxyUsername = proxyInfo.getUserName(); String proxyPassword = proxyInfo.getPassword(); String proxyNtlmHost = proxyInfo.getNtlmHost(); String proxyNtlmDomain = proxyInfo.getNtlmDomain(); if (proxyUsername != null && proxyPassword != null) { Credentials creds; if (proxyNtlmHost != null || proxyNtlmDomain != null) { creds = new NTCredentials(proxyUsername, proxyPassword, proxyNtlmHost, proxyNtlmDomain); } else { creds = new UsernamePasswordCredentials(proxyUsername, proxyPassword); } getCredentialsProvider().setCredentials(proxyScope, creds); BasicScheme proxyAuth = new BasicScheme(); proxyAuth.processChallenge(new BasicHeader(AUTH.PROXY_AUTH, "BASIC preemptive")); getAuthCache().put(proxyHost, proxyAuth); } } } return client.execute(httpMethod, getLocalContext()); } @Override public void connect(Repository repository, AuthenticationInfo authenticationInfo, ProxyInfoProvider proxyInfoProvider) throws ConnectionException, AuthenticationException { if (repository == null) { throw new IllegalStateException("The repository specified cannot be null."); } if (authenticationInfo == null) { authenticationInfo = new AuthenticationInfo(); } if (authenticationInfo.getUserName() == null) { // Get user/pass that were encoded in the URL. if (repository.getUsername() != null) { // Need to decode username/password because it may contain encoded characters (http://www.w3schools.com/tags/ref_urlencode.asp) // A common encoding is to provide a username as an email address like user%40domain.org authenticationInfo.setUserName(URLUtils.decode(repository.getUsername())); if (repository.getPassword() != null && authenticationInfo.getPassword() == null) { authenticationInfo.setPassword(URLUtils.decode(repository.getPassword())); } } } super.connect(repository, authenticationInfo, proxyInfoProvider); } private AuthCache getAuthCache() { return getField(AuthCache.class, "authCache"); } private CredentialsProvider getCredentialsProvider() { return getField(CredentialsProvider.class, "credentialsProvider"); } private HttpClientContext getLocalContext() { return getField(HttpClientContext.class, "localContext"); } private <T> T getField(Class<T> clazz, String name) { try { Field field = AbstractHttpClientWagon.class.getDeclaredField(name); field.setAccessible(true); return clazz.cast(field.get(this)); } catch (NoSuchFieldException e) { throw new IllegalStateException("Unable to retrieve field " + name, e); } catch (IllegalAccessException e) { throw new IllegalStateException("Unable to retrieve field " + name, e); } } private void copyConfig(HttpMethodConfiguration config, RequestConfig.Builder builder) { try { Class<?> clazz = getClass().getClassLoader() .loadClass("org.apache.maven.wagon.providers.http.ConfigurationUtils"); Method method = clazz.getMethod("copyConfig", HttpMethodConfiguration.class, RequestConfig.Builder.class); method.invoke(null, config, builder); } catch (ClassNotFoundException e) { throw new IllegalStateException("Unable to call copyConfig", e); } catch (InvocationTargetException e) { throw new IllegalStateException("Unable to call copyConfig", e); } catch (NoSuchMethodException e) { throw new IllegalStateException("Unable to call copyConfig", e); } catch (IllegalAccessException e) { throw new IllegalStateException("Unable to call copyConfig", e); } } }