• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
ApacheHTTPSender()65     ApacheHTTPSender() {
66         // Load Apache HTTP client class
67         HttpClient.class.getName();
68     }
69 
70     ///////////////////////////////////////////////////////////////////////////
71     // HTTPSender interface methods:
72 
73     /**
74      * {@inheritDoc}
75      */
init(final BOSHClientConfig session)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      */
destroy()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      */
send( final CMSessionParams params, final AbstractBody body)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 
initHttpClient(final BOSHClientConfig config)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