/* * Copyright 2008-2012 Zuse Institute Berlin (ZIB) * 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 de.zib.gndms.gndmc.utils; import de.zib.gndms.common.kit.security.CustomSSLContextRequestFactory; import de.zib.gndms.common.kit.security.SetupSSL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; import org.springframework.web.client.RequestCallback; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.ResponseExtractor; import org.springframework.web.client.RestTemplate; import javax.net.ssl.SSLContext; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @date: 14.03.12 * @time: 13:06 * @author: Jörg Bachmann * @email: bachmann@zib.de */ public class HTTPGetter { protected final Logger logger = LoggerFactory.getLogger( this.getClass() ); private int timeout = 10000; // default: 10ms private String keyStoreLocation; private String trustStoreLocation; private String password; // TODO: don't use same password for keystore and key?! private SSLContext sslContext; final private Map< Integer, EnhancedResponseExtractor > extractorMap; public HTTPGetter() { extractorMap = new HashMap< Integer, EnhancedResponseExtractor >(); resetExtractorMap(); } public void resetExtractorMap() { logger.trace( "Resetting ResponseExtractorMap." ); extractorMap.clear(); extractorMap.put( 3, new RedirectResponseExtractor() ); extractorMap.put( 0, new DefaultResponseExtractor() ); } public EnhancedResponseExtractor getResponseExtractor( int statusCode ) { return extractorMap.get( statusCode ); } public void setupSSL( SetupSSL setupSSL, final String keyPassword ) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException { sslContext = setupSSL.setupSSLContext( keyPassword ); } public void setExtractor( int httpStatusCode, EnhancedResponseExtractor responseExtractor ) { logger.trace( "Setting ResponseExtractor " + responseExtractor.getClass().getCanonicalName() + " for HTTP status code " + httpStatusCode ); extractorMap.put( httpStatusCode, responseExtractor ); } public int get( String url ) throws NoSuchAlgorithmException, KeyManagementException { return get( HttpMethod.GET, url, ( HttpHeaders )null ); } public int get( String url, final HttpHeaders headers ) throws NoSuchAlgorithmException, KeyManagementException { return get( HttpMethod.GET, url, headers ); } private EnhancedResponseExtractor get( final String url, final RequestCallback requestCallback ) throws NoSuchAlgorithmException, KeyManagementException { return get( HttpMethod.GET, url, requestCallback ); } public int head( String url ) throws NoSuchAlgorithmException, KeyManagementException { return get(HttpMethod.HEAD, url, (HttpHeaders) null); } public int head( String url, final HttpHeaders headers ) throws NoSuchAlgorithmException, KeyManagementException { return get( HttpMethod.HEAD, url, headers ); } private EnhancedResponseExtractor head( final String url, final RequestCallback requestCallback ) throws NoSuchAlgorithmException, KeyManagementException { return get( HttpMethod.HEAD, url, requestCallback ); } public int get( final HttpMethod method, String url ) throws NoSuchAlgorithmException, KeyManagementException { return get( method, url, ( HttpHeaders )null ); } public int get( final HttpMethod method, String url, final HttpHeaders headers ) throws NoSuchAlgorithmException, KeyManagementException { logger.debug(method.toString() + " URL " + url); EnhancedResponseExtractor responseExtractor = get( method, url, new RequestCallback() { @Override public void doWithRequest( ClientHttpRequest request ) throws IOException { // add headers if( headers != null ) request.getHeaders().putAll( headers ); } } ); int statusCode = responseExtractor.getStatusCode(); int redirectionCounter = 0; // redirect as long as needed while( 300 <= statusCode && statusCode < 400 ) { final List< String > cookies = DefaultResponseExtractor.getCookies( responseExtractor.getHeaders() ); final String location = DefaultResponseExtractor.getLocation( responseExtractor.getHeaders() ); logger.debug( "Redirection " + ++redirectionCounter ); logger.trace( "Redirecting to " + location + " with cookies " + cookies.toString() ); responseExtractor = get( method, location, new RequestCallback() { @Override public void doWithRequest( ClientHttpRequest request ) throws IOException { for( String c: cookies ) request.getHeaders().add( "Cookie", c.split( ";", 2 )[0] ); // add headers if( headers != null ) request.getHeaders().putAll( headers ); } }); statusCode = responseExtractor.getStatusCode(); } logger.debug( "HTTP " + method.toString() + " Status Code " + statusCode + " after " + redirectionCounter + " redirections"); return statusCode; } private EnhancedResponseExtractor get( final HttpMethod method, final String url, final RequestCallback requestCallback ) throws NoSuchAlgorithmException, KeyManagementException { CustomSSLContextRequestFactory requestFactory = new CustomSSLContextRequestFactory( sslContext ); RestTemplate rt = new RestTemplate( requestFactory ); requestFactory.setConnectTimeout( getTimeout() ); requestFactory.setReadTimeout( getTimeout() ); try { return rt.execute( url, method, requestCallback, new ResponseExtractor< EnhancedResponseExtractor >() { // call the EnhancedResponseExtractor registered for this response.statusCode @Override public EnhancedResponseExtractor extractData( ClientHttpResponse response ) throws IOException { int statusCode = response.getStatusCode().value(); EnhancedResponseExtractor enhancedResponseExtractor = extractorMap.get( statusCode ); if( null == enhancedResponseExtractor ) enhancedResponseExtractor = extractorMap.get( statusCode / 100 ); if( null == enhancedResponseExtractor ) enhancedResponseExtractor = extractorMap.get( 0 ); if( null == enhancedResponseExtractor ) throw new IllegalStateException( "No default ResponseExtractor registered. THIS IS NOT HAPPENING :/" ); enhancedResponseExtractor.extractData(url, response); return enhancedResponseExtractor; } } ); } catch( ResourceAccessException e ) { throw new RuntimeException( "Could not connect to " + url + ": " + e.getMessage(), e ); } } public String getKeyStoreLocation() { return keyStoreLocation; } public void setKeyStoreLocation( String keyStoreLocation ) { this.keyStoreLocation = keyStoreLocation; } public String getTrustStoreLocation() { return trustStoreLocation; } public void setTrustStoreLocation( String trustStoreLocation ) { this.trustStoreLocation = trustStoreLocation; } public void setPassword( String password ) { this.password = password; } public int getTimeout() { return timeout; } public void setTimeout( int timeout ) { this.timeout = timeout; } }