View Javadoc

1   package com.terradue.jcatalogue.client.internal.ahc;
2   
3   import static com.terradue.jcatalogue.client.internal.lang.Assertions.checkArgument;
4   import static com.terradue.jcatalogue.client.internal.lang.Assertions.checkNotNull;
5   import static java.util.Arrays.asList;
6   
7   import java.io.File;
8   import java.net.URI;
9   import java.security.KeyStore;
10  import java.util.ArrayList;
11  import java.util.HashMap;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.concurrent.ConcurrentHashMap;
15  import java.util.concurrent.ConcurrentMap;
16  
17  import javax.net.ssl.KeyManager;
18  import javax.net.ssl.KeyManagerFactory;
19  import javax.net.ssl.SSLContext;
20  import javax.net.ssl.TrustManager;
21  
22  import org.apache.commons.ssl.KeyMaterial;
23  
24  import com.ning.http.client.AsyncHandler;
25  import com.ning.http.client.AsyncHttpClient;
26  import com.ning.http.client.AsyncHttpClientConfig;
27  import com.ning.http.client.Cookie;
28  import com.ning.http.client.Realm;
29  import com.ning.http.client.RequestBuilder;
30  import com.ning.http.client.resumable.ResumableIOExceptionFilter;
31  import com.terradue.jcatalogue.client.HttpAuthScheme;
32  import com.terradue.jcatalogue.client.HttpMethod;
33  import com.terradue.jcatalogue.client.Parameter;
34  
35  /**
36   * @since 0.8
37   */
38  public final class HttpInvoker
39  {
40  
41      private final Map<String, Realm> realms = new HashMap<String, Realm>();
42  
43      private final List<KeyManager> keyManagers = new ArrayList<KeyManager>();
44  
45      private final TrustManager[] trustManagers = new TrustManager[] { new DummyTrustManager() };
46  
47      private final ConcurrentMap<String, ConcurrentMap<String, Cookie>> cookiesRegistry = new ConcurrentHashMap<String, ConcurrentMap<String, Cookie>>();
48  
49      private final ConcurrentMap<String, UmSsoAccess> umSsoCredentials = new ConcurrentHashMap<String, UmSsoAccess>();
50  
51      private final AsyncHttpClient httpClient;
52  
53      public HttpInvoker()
54      {
55          SSLContext context = null;
56          try
57          {
58              context = SSLContext.getInstance( "TLS" );
59              context.init( new KeyManager[] {}, trustManagers, null );
60          }
61          catch ( Exception e )
62          {
63              throw new IllegalStateException( "Impossible to initialize SSL context", e );
64          }
65  
66          int timeout = 45 * 60 * 60 * 1000; // 45 minutes
67  
68          httpClient = new AsyncHttpClient( new AsyncHttpClientConfig.Builder()
69                                                  .setRequestTimeoutInMs( timeout )
70                                                  .setAllowPoolingConnection( true )
71                                                  .addIOExceptionFilter( new ResumableIOExceptionFilter() )
72                                                  .setMaximumConnectionsPerHost( 10 )
73                                                  .setMaximumConnectionsTotal( 100 )
74                                                  .addResponseFilter( new UmSsoStatusResponseFilter( umSsoCredentials,
75                                                                                                     cookiesRegistry ) )
76                                                  .setFollowRedirects( true )
77                                                  .setMaximumNumberOfRedirects( Integer.MAX_VALUE ) // thanks ESA guys
78                                                  .setSSLContext( context )
79                                                  .build() );
80      }
81  
82      public <T> T invoke( HttpMethod httpMethod, URI uri, AsyncHandler<T> handler, Parameter...parameters )
83      {
84          checkNotNull( uri, "Input URI cannot be null" );
85  
86          RequestBuilder requestBuilder = new RequestBuilder( httpMethod.toString() ).setUrl( uri.toString() );
87  
88          // send all domain cookies, if any
89          Map<String, Cookie> domainCookies = cookiesRegistry.get( uri.getHost() );
90          if ( domainCookies != null && !domainCookies.isEmpty() )
91          {
92              for ( Cookie cookie : domainCookies.values() )
93              {
94                  requestBuilder.addCookie( cookie );
95              }
96          }
97  
98          // send all parameters
99          for ( Parameter parameter : parameters )
100         {
101             if ( HttpMethod.GET == httpMethod )
102             {
103                 requestBuilder.addQueryParameter( parameter.getName(), parameter.getValue() );
104             }
105             else
106             {
107                 requestBuilder.addParameter( parameter.getName(), parameter.getValue() );
108             }
109         }
110 
111         // send the realms authentication, if any
112         if ( realms.containsKey( uri.getHost() ) )
113         {
114             requestBuilder.setRealm( realms.get( uri.getHost() ) );
115         }
116 
117         try
118         {
119             return httpClient.executeRequest( requestBuilder.build(), handler ).get();
120         }
121         catch ( Exception e )
122         {
123             throw new RuntimeException( "An error occurred while invoking " + uri, e );
124         }
125     }
126 
127     public void registerRealm( String host, String username, String password, boolean preemptive, HttpAuthScheme authScheme )
128     {
129         host = checkNotNull( host, "host cannot be null" );
130         username = checkNotNull( username, "username cannot be null" );
131         password = checkNotNull( password, "password cannot be null" );
132         authScheme = checkNotNull( authScheme, "authScheme cannot be null" );
133 
134         realms.put( host, new Realm.RealmBuilder()
135                                    .setPrincipal( username )
136                                    .setPassword( password )
137                                    .setUsePreemptiveAuth( preemptive )
138                                    .setScheme( authScheme.getAuthScheme() )
139                                    .build() );
140     }
141 
142     public void registerSSLProxy( File proxyCertificate )
143     {
144         registerSSLCerificates( proxyCertificate, proxyCertificate, null );
145     }
146 
147     /**
148      * @since 0.7
149      */
150     public void registerSSLCerificates( File sslCertificate, File sslKey, String sslPassword )
151     {
152         checkFile( sslCertificate );
153         checkFile( sslKey );
154 
155         if ( sslPassword == null )
156         {
157             sslPassword = "";
158         }
159 
160         final char[] password = sslPassword.toCharArray();
161 
162         try
163         {
164             final KeyStore store = new KeyMaterial( sslCertificate, sslKey, password ).getKeyStore();
165             store.load( null, password );
166 
167             // initialize key and trust managers -> default behavior
168             final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( "SunX509" );
169             // password for key and store have to be the same IIRC
170             keyManagerFactory.init( store, password );
171 
172             keyManagers.addAll( asList( keyManagerFactory.getKeyManagers() ) );
173 
174             httpClient.getConfig().getSSLContext().init( keyManagers.toArray( new KeyManager[keyManagers.size()] ),
175                                                          trustManagers,
176                                                          null );
177         }
178         catch ( Exception e )
179         {
180             throw new IllegalStateException( "Impossible to initialize SSL certificate/key", e );
181         }
182     }
183 
184     private static void checkFile( File file )
185     {
186         checkArgument( file.exists(), "File %s not found, please verify it exists", file );
187         checkArgument( !file.isDirectory(), "File %s must be not a directory", file );
188     }
189 
190     public void registerUmSsoAccess( String loginFormUrl, HttpMethod httpMethod, Parameter...parameters )
191     {
192         loginFormUrl = checkNotNull( loginFormUrl, "loginFormUrl cannot be null" );
193 
194         registerUmSsoCredentials( URI.create( loginFormUrl ), httpMethod, parameters );
195     }
196 
197     public void registerUmSsoCredentials( URI loginFormUrl, HttpMethod httpMethod, Parameter...parameters )
198     {
199         loginFormUrl = checkNotNull( loginFormUrl, "loginFormUrl cannot be null" );
200         httpMethod = checkNotNull( httpMethod, "httpMethod cannot be null" );
201         parameters = checkNotNull( parameters, "loginFormUrl cannot be null" );
202 
203         umSsoCredentials.put( loginFormUrl.getHost(), new UmSsoAccess( loginFormUrl, httpMethod, parameters ) );
204     }
205 
206     public void shutDown()
207     {
208         httpClient.close();
209     }
210 
211 }