HttpUtils.java revision 86a1cf79bf92dbb2b9d09431379bff6de83c2581
1/* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mms.transaction; 19import org.apache.http.HttpEntity; 20import org.apache.http.HttpHost; 21import org.apache.http.HttpRequest; 22import org.apache.http.HttpResponse; 23import org.apache.http.StatusLine; 24import org.apache.http.client.HttpClient; 25import org.apache.http.client.methods.HttpGet; 26import org.apache.http.client.methods.HttpPost; 27import org.apache.http.conn.params.ConnRouteParams; 28import org.apache.http.params.HttpParams; 29import org.apache.http.params.HttpProtocolParams; 30 31import com.android.mms.MmsConfig; 32 33import android.content.Context; 34import android.net.http.AndroidHttpClient; 35import android.provider.Settings; 36import android.util.Config; 37import android.util.Log; 38 39import java.io.DataInputStream; 40import java.io.IOException; 41import java.net.SocketException; 42import java.net.URI; 43import java.net.URISyntaxException; 44import java.util.Locale; 45 46public class HttpUtils { 47 private static final String TAG = "HttpUtils"; 48 private static final boolean DEBUG = false; 49 private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV; 50 51 public static final int HTTP_POST_METHOD = 1; 52 public static final int HTTP_GET_METHOD = 2; 53 54 // This is the value to use for the "Accept-Language" header. 55 // Once it becomes possible for the user to change the locale 56 // setting, this should no longer be static. We should call 57 // getHttpAcceptLanguage instead. 58 private static final String HDR_VALUE_ACCEPT_LANGUAGE; 59 60 static { 61 HDR_VALUE_ACCEPT_LANGUAGE = getHttpAcceptLanguage(); 62 } 63 64 // Definition for necessary HTTP headers. 65 private static final String HDR_KEY_ACCEPT = "Accept"; 66 private static final String HDR_KEY_ACCEPT_LANGUAGE = "Accept-Language"; 67 private static final String HDR_KEY_X_WAP_PROFILE = "x-wap-profile"; 68 69 private static final String HDR_VALUE_ACCEPT = 70 "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic"; 71 72 private HttpUtils() { 73 // To forbidden instantiate this class. 74 } 75 76 /** 77 * A helper method to send or retrieve data through HTTP protocol. 78 * 79 * @param token The token to identify the sending progress. 80 * @param url The URL used in a GET request. Null when the method is 81 * HTTP_POST_METHOD. 82 * @param pdu The data to be POST. Null when the method is HTTP_GET_METHOD. 83 * @param method HTTP_POST_METHOD or HTTP_GET_METHOD. 84 * @return A byte array which contains the response data. 85 * If an HTTP error code is returned, an IOException will be thrown. 86 * @throws IOException if any error occurred on network interface or 87 * an HTTP error code(>=400) returned from the server. 88 */ 89 protected static byte[] httpConnection(Context context, long token, 90 String url, byte[] pdu, int method, boolean isProxySet, 91 String proxyHost, int proxyPort) throws IOException { 92 if (url == null) { 93 throw new IllegalArgumentException("URL must not be null."); 94 } 95 96 if (LOCAL_LOGV) { 97 Log.v(TAG, "httpConnection: params list"); 98 Log.v(TAG, "\ttoken\t\t= " + token); 99 Log.v(TAG, "\turl\t\t= " + url); 100 Log.v(TAG, "\tmethod\t\t= " 101 + ((method == HTTP_POST_METHOD) ? "POST" 102 : ((method == HTTP_GET_METHOD) ? "GET" : "UNKNOWN"))); 103 Log.v(TAG, "\tisProxySet\t= " + isProxySet); 104 Log.v(TAG, "\tproxyHost\t= " + proxyHost); 105 Log.v(TAG, "\tproxyPort\t= " + proxyPort); 106 // TODO Print out binary data more readable. 107 //Log.v(TAG, "\tpdu\t\t= " + Arrays.toString(pdu)); 108 } 109 110 AndroidHttpClient client = null; 111 112 try { 113 // Make sure to use a proxy which supports CONNECT. 114 URI hostUrl = new URI(url); 115 HttpHost target = new HttpHost( 116 hostUrl.getHost(), hostUrl.getPort(), 117 HttpHost.DEFAULT_SCHEME_NAME); 118 119 client = createHttpClient(); 120 HttpRequest req = null; 121 switch(method) { 122 case HTTP_POST_METHOD: 123 ProgressCallbackEntity entity = new ProgressCallbackEntity( 124 context, token, pdu); 125 // Set request content type. 126 entity.setContentType("application/vnd.wap.mms-message"); 127 128 HttpPost post = new HttpPost(url); 129 post.setEntity(entity); 130 req = post; 131 break; 132 case HTTP_GET_METHOD: 133 req = new HttpGet(url); 134 break; 135 default: 136 Log.e(TAG, "Unknown HTTP method: " + method 137 + ". Must be one of POST[" + HTTP_POST_METHOD 138 + "] or GET[" + HTTP_GET_METHOD + "]."); 139 return null; 140 } 141 142 // Set route parameters for the request. 143 HttpParams params = client.getParams(); 144 if (isProxySet) { 145 ConnRouteParams.setDefaultProxy( 146 params, new HttpHost(proxyHost, proxyPort)); 147 } 148 req.setParams(params); 149 150 // Set necessary HTTP headers for MMS transmission. 151 req.addHeader(HDR_KEY_ACCEPT, HDR_VALUE_ACCEPT); 152 { 153 String xWapProfileUrl = MmsConfig.getUaProfUrl(); 154 155 if (xWapProfileUrl != null) { 156 req.addHeader(HDR_KEY_X_WAP_PROFILE, xWapProfileUrl); 157 } 158 } 159 req.addHeader(HDR_KEY_ACCEPT_LANGUAGE, HDR_VALUE_ACCEPT_LANGUAGE); 160 161 HttpResponse response = client.execute(target, req); 162 StatusLine status = response.getStatusLine(); 163 if (status.getStatusCode() != 200) { // HTTP 200 is success. 164 throw new IOException("HTTP error: " + status.getReasonPhrase()); 165 } 166 167 HttpEntity entity = response.getEntity(); 168 byte[] body = null; 169 if (entity != null) { 170 try { 171 if (entity.getContentLength() > 0) { 172 body = new byte[(int) entity.getContentLength()]; 173 DataInputStream dis = new DataInputStream(entity.getContent()); 174 try { 175 dis.readFully(body); 176 } finally { 177 try { 178 dis.close(); 179 } catch (IOException e) { 180 Log.e(TAG, "Error closing input stream: " + e.getMessage()); 181 } 182 } 183 } 184 } finally { 185 if (entity != null) { 186 entity.consumeContent(); 187 } 188 } 189 } 190 return body; 191 } catch (URISyntaxException e) { 192 handleHttpConnectionException(e); 193 } catch (IllegalStateException e) { 194 handleHttpConnectionException(e); 195 } catch (IllegalArgumentException e) { 196 handleHttpConnectionException(e); 197 } catch (SocketException e) { 198 handleHttpConnectionException(e); 199 } catch (Exception e) { 200 handleHttpConnectionException(e); 201 } 202 finally { 203 if (client != null) { 204 client.close(); 205 } 206 } 207 return null; 208 } 209 210 private static void handleHttpConnectionException(Exception exception) 211 throws IOException { 212 // Inner exception should be logged to make life easier. 213 Log.e(TAG, exception.getMessage()); 214 throw new IOException(exception.getMessage()); 215 } 216 217 private static AndroidHttpClient createHttpClient() { 218 AndroidHttpClient client 219 = AndroidHttpClient.newInstance("Android-Mms/0.1"); 220 HttpParams params = client.getParams(); 221 HttpProtocolParams.setContentCharset(params, "UTF-8"); 222 return client; 223 } 224 225 /** 226 * Return the Accept-Language header. Use the current locale plus 227 * US if we are in a different locale than US. 228 */ 229 private static String getHttpAcceptLanguage() { 230 Locale locale = Locale.getDefault(); 231 StringBuilder builder = new StringBuilder(); 232 233 addLocaleToHttpAcceptLanguage(builder, locale); 234 if (!locale.equals(Locale.US)) { 235 if (builder.length() > 0) { 236 builder.append(", "); 237 } 238 addLocaleToHttpAcceptLanguage(builder, Locale.US); 239 } 240 return builder.toString(); 241 } 242 243 private static void addLocaleToHttpAcceptLanguage( 244 StringBuilder builder, Locale locale) { 245 String language = locale.getLanguage(); 246 247 if (language != null) { 248 builder.append(language); 249 250 String country = locale.getCountry(); 251 252 if (country != null) { 253 builder.append("-"); 254 builder.append(country); 255 } 256 } 257 } 258} 259