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