Home | History | Annotate | Download | only in jbosh
      1 /*
      2  * Copyright 2009 Guenther Niess
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.kenai.jbosh;
     18 
     19 import java.util.concurrent.locks.Lock;
     20 import java.util.concurrent.locks.ReentrantLock;
     21 
     22 import org.apache.http.HttpHost;
     23 import org.apache.http.HttpVersion;
     24 import org.apache.http.client.HttpClient;
     25 import org.apache.http.conn.ClientConnectionManager;
     26 import org.apache.http.conn.params.ConnManagerParams;
     27 import org.apache.http.conn.params.ConnRoutePNames;
     28 import org.apache.http.conn.scheme.PlainSocketFactory;
     29 import org.apache.http.conn.scheme.Scheme;
     30 import org.apache.http.conn.scheme.SchemeRegistry;
     31 import org.apache.http.conn.ssl.SSLSocketFactory;
     32 import org.apache.http.impl.client.DefaultHttpClient;
     33 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
     34 import org.apache.http.params.BasicHttpParams;
     35 import org.apache.http.params.HttpParams;
     36 import org.apache.http.params.HttpProtocolParams;
     37 
     38 /**
     39  * Implementation of the {@code HTTPSender} interface which uses the
     40  * Apache HttpClient API to send messages to the connection manager.
     41  */
     42 final class ApacheHTTPSender implements HTTPSender {
     43 
     44     /**
     45      * Lock used for internal synchronization.
     46      */
     47     private final Lock lock = new ReentrantLock();
     48 
     49     /**
     50      * Session configuration.
     51      */
     52     private BOSHClientConfig cfg;
     53 
     54     /**
     55      * HttpClient instance to use to communicate.
     56      */
     57     private HttpClient httpClient;
     58 
     59     ///////////////////////////////////////////////////////////////////////////
     60     // Constructors:
     61 
     62     /**
     63      * Prevent construction apart from our package.
     64      */
     65     ApacheHTTPSender() {
     66         // Load Apache HTTP client class
     67         HttpClient.class.getName();
     68     }
     69 
     70     ///////////////////////////////////////////////////////////////////////////
     71     // HTTPSender interface methods:
     72 
     73     /**
     74      * {@inheritDoc}
     75      */
     76     public void init(final BOSHClientConfig session) {
     77         lock.lock();
     78         try {
     79             cfg = session;
     80             httpClient = initHttpClient(session);
     81         } finally {
     82             lock.unlock();
     83         }
     84     }
     85 
     86     /**
     87      * {@inheritDoc}
     88      */
     89     public void destroy() {
     90         lock.lock();
     91         try {
     92             if (httpClient != null) {
     93                 httpClient.getConnectionManager().shutdown();
     94             }
     95         } finally {
     96             cfg = null;
     97             httpClient = null;
     98             lock.unlock();
     99         }
    100     }
    101 
    102     /**
    103      * {@inheritDoc}
    104      */
    105     public HTTPResponse send(
    106             final CMSessionParams params,
    107             final AbstractBody body) {
    108         HttpClient mClient;
    109         BOSHClientConfig mCfg;
    110         lock.lock();
    111         try {
    112             if (httpClient == null) {
    113                 httpClient = initHttpClient(cfg);
    114             }
    115             mClient = httpClient;
    116             mCfg = cfg;
    117         } finally {
    118             lock.unlock();
    119         }
    120         return new ApacheHTTPResponse(mClient, mCfg, params, body);
    121     }
    122 
    123     ///////////////////////////////////////////////////////////////////////////
    124     // Package-private methods:
    125 
    126     private synchronized HttpClient initHttpClient(final BOSHClientConfig config) {
    127         // Create and initialize HTTP parameters
    128         HttpParams params = new BasicHttpParams();
    129         ConnManagerParams.setMaxTotalConnections(params, 100);
    130         HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    131         HttpProtocolParams.setUseExpectContinue(params, false);
    132         if (config != null &&
    133                 config.getProxyHost() != null &&
    134                 config.getProxyPort() != 0) {
    135             HttpHost proxy = new HttpHost(
    136                     config.getProxyHost(),
    137                     config.getProxyPort());
    138             params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
    139         }
    140 
    141         // Create and initialize scheme registry
    142         SchemeRegistry schemeRegistry = new SchemeRegistry();
    143         schemeRegistry.register(
    144                 new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    145             SSLSocketFactory sslFactory = SSLSocketFactory.getSocketFactory();
    146             sslFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    147             schemeRegistry.register(
    148                     new Scheme("https", sslFactory, 443));
    149 
    150         // Create an HttpClient with the ThreadSafeClientConnManager.
    151         // This connection manager must be used if more than one thread will
    152         // be using the HttpClient.
    153         ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
    154         return new DefaultHttpClient(cm, params);
    155     }
    156 }
    157