1/* 2 * Copyright (C) 2014 The Android Open Source Project 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 17package com.android.inputmethod.latin.network; 18 19import android.util.Log; 20 21import java.io.BufferedOutputStream; 22import java.io.IOException; 23import java.io.InputStream; 24import java.io.OutputStream; 25import java.net.HttpURLConnection; 26 27import javax.annotation.Nonnull; 28import javax.annotation.Nullable; 29 30/** 31 * A client for executing HTTP requests synchronously. 32 * This must never be called from the main thread. 33 */ 34public class BlockingHttpClient { 35 private static final boolean DEBUG = false; 36 private static final String TAG = BlockingHttpClient.class.getSimpleName(); 37 38 private final HttpURLConnection mConnection; 39 40 /** 41 * Interface that handles processing the response for a request. 42 */ 43 public interface ResponseProcessor<T> { 44 /** 45 * Called when the HTTP request finishes successfully. 46 * The {@link InputStream} is closed by the client after the method finishes, 47 * so any processing must be done in this method itself. 48 * 49 * @param response An input stream that can be used to read the HTTP response. 50 */ 51 T onSuccess(InputStream response) throws IOException; 52 } 53 54 public BlockingHttpClient(HttpURLConnection connection) { 55 mConnection = connection; 56 } 57 58 /** 59 * Executes the request on the underlying {@link HttpURLConnection}. 60 * 61 * @param request The request payload, if any, or null. 62 * @param responseProcessor A processor for the HTTP response. 63 */ 64 public <T> T execute(@Nullable byte[] request, @Nonnull ResponseProcessor<T> responseProcessor) 65 throws IOException, AuthException, HttpException { 66 if (DEBUG) { 67 Log.d(TAG, "execute: " + mConnection.getURL()); 68 } 69 try { 70 if (request != null) { 71 if (DEBUG) { 72 Log.d(TAG, "request size: " + request.length); 73 } 74 OutputStream out = new BufferedOutputStream(mConnection.getOutputStream()); 75 out.write(request); 76 out.flush(); 77 out.close(); 78 } 79 80 final int responseCode = mConnection.getResponseCode(); 81 if (responseCode != HttpURLConnection.HTTP_OK) { 82 Log.w(TAG, "Response error: " + responseCode + ", Message: " 83 + mConnection.getResponseMessage()); 84 if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { 85 throw new AuthException(mConnection.getResponseMessage()); 86 } 87 throw new HttpException(responseCode); 88 } 89 if (DEBUG) { 90 Log.d(TAG, "request executed successfully"); 91 } 92 return responseProcessor.onSuccess(mConnection.getInputStream()); 93 } finally { 94 mConnection.disconnect(); 95 } 96 } 97} 98