| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.gallery3d.picasa; |
| |
| import android.text.TextUtils; |
| import android.util.Log; |
| |
| import org.apache.http.Header; |
| import org.apache.http.HttpEntity; |
| import org.apache.http.HttpResponse; |
| import org.apache.http.client.methods.HttpGet; |
| import org.apache.http.client.methods.HttpPost; |
| import org.apache.http.client.methods.HttpUriRequest; |
| import org.apache.http.client.params.HttpClientParams; |
| import org.apache.http.conn.scheme.PlainSocketFactory; |
| import org.apache.http.conn.scheme.Scheme; |
| import org.apache.http.conn.scheme.SchemeRegistry; |
| import org.apache.http.entity.ByteArrayEntity; |
| import org.apache.http.entity.InputStreamEntity; |
| import org.apache.http.impl.client.DefaultHttpClient; |
| import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; |
| import org.apache.http.params.BasicHttpParams; |
| import org.apache.http.params.HttpConnectionParams; |
| import org.apache.http.params.HttpParams; |
| import org.apache.http.params.HttpProtocolParams; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.util.zip.GZIPInputStream; |
| import java.util.zip.GZIPOutputStream; |
| |
| public final class GDataClient { |
| private static final String TAG = "GDataClient"; |
| private static final String USER_AGENT = "GData/1.0; gzip"; |
| private static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override"; |
| private static final String IF_MATCH = "If-Match"; |
| private static final int CONNECTION_TIMEOUT = 20000; // ms. |
| private static final int MIN_GZIP_SIZE = 512; |
| public static final HttpParams HTTP_PARAMS; |
| public static final ThreadSafeClientConnManager HTTP_CONNECTION_MANAGER; |
| |
| private final DefaultHttpClient mHttpClient = |
| new DefaultHttpClient(HTTP_CONNECTION_MANAGER, HTTP_PARAMS); |
| private String mAuthToken; |
| |
| static { |
| // Prepare HTTP parameters. |
| HttpParams params = new BasicHttpParams(); |
| HttpConnectionParams.setStaleCheckingEnabled(params, false); |
| HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT); |
| HttpConnectionParams.setSoTimeout(params, CONNECTION_TIMEOUT); |
| HttpClientParams.setRedirecting(params, true); |
| HttpProtocolParams.setUserAgent(params, USER_AGENT); |
| HTTP_PARAMS = params; |
| |
| // Register HTTP protocol. |
| SchemeRegistry schemeRegistry = new SchemeRegistry(); |
| schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); |
| |
| // Create the connection manager. |
| HTTP_CONNECTION_MANAGER = new ThreadSafeClientConnManager(params, schemeRegistry); |
| } |
| |
| public static final class Operation { |
| public String inOutEtag; |
| public int outStatus; |
| public InputStream outBody; |
| } |
| |
| public void setAuthToken(String authToken) { |
| mAuthToken = authToken; |
| } |
| |
| public void get(String feedUrl, Operation operation) throws IOException { |
| callMethod(new HttpGet(feedUrl), operation); |
| } |
| |
| public void post(String feedUrl, byte[] data, String contentType, Operation operation) |
| throws IOException { |
| ByteArrayEntity entity = getCompressedEntity(data); |
| entity.setContentType(contentType); |
| HttpPost post = new HttpPost(feedUrl); |
| post.setEntity(entity); |
| callMethod(post, operation); |
| } |
| |
| public void put(String feedUrl, byte[] data, String contentType, Operation operation) |
| throws IOException { |
| ByteArrayEntity entity = getCompressedEntity(data); |
| entity.setContentType(contentType); |
| HttpPost post = new HttpPost(feedUrl); |
| post.setHeader(X_HTTP_METHOD_OVERRIDE, "PUT"); |
| post.setEntity(entity); |
| callMethod(post, operation); |
| } |
| |
| public void putStream(String feedUrl, InputStream stream, String contentType, |
| Operation operation) throws IOException { |
| InputStreamEntity entity = new InputStreamEntity(stream, -1); |
| entity.setContentType(contentType); |
| HttpPost post = new HttpPost(feedUrl); |
| post.setHeader(X_HTTP_METHOD_OVERRIDE, "PUT"); |
| post.setEntity(entity); |
| callMethod(post, operation); |
| } |
| |
| public void delete(String feedUrl, Operation operation) throws IOException { |
| HttpPost post = new HttpPost(feedUrl); |
| String etag = operation.inOutEtag; |
| post.setHeader(X_HTTP_METHOD_OVERRIDE, "DELETE"); |
| post.setHeader(IF_MATCH, etag != null ? etag : "*"); |
| callMethod(post, operation); |
| } |
| |
| private void callMethod(HttpUriRequest request, Operation operation) throws IOException { |
| // Specify GData protocol version 2.0. |
| request.addHeader("GData-Version", "2"); |
| |
| // Indicate support for gzip-compressed responses. |
| request.addHeader("Accept-Encoding", "gzip"); |
| |
| // Specify authorization token if provided. |
| String authToken = mAuthToken; |
| if (!TextUtils.isEmpty(authToken)) { |
| request.addHeader("Authorization", "GoogleLogin auth=" + authToken); |
| } |
| |
| // Specify the ETag of a prior response, if available. |
| String etag = operation.inOutEtag; |
| if (etag != null) { |
| request.addHeader("If-None-Match", etag); |
| } |
| |
| // Execute the HTTP request. |
| HttpResponse httpResponse = null; |
| try { |
| httpResponse = mHttpClient.execute(request); |
| } catch (IOException e) { |
| Log.w(TAG, "Request failed: " + request.getURI()); |
| throw e; |
| } |
| |
| // Get the status code and response body. |
| int status = httpResponse.getStatusLine().getStatusCode(); |
| InputStream stream = null; |
| HttpEntity entity = httpResponse.getEntity(); |
| if (entity != null) { |
| // Wrap the entity input stream in a GZIP decoder if necessary. |
| stream = entity.getContent(); |
| if (stream != null) { |
| Header header = entity.getContentEncoding(); |
| if (header != null) { |
| if (header.getValue().contains("gzip")) { |
| stream = new GZIPInputStream(stream); |
| } |
| } |
| } |
| } |
| |
| // Return the stream if successful. |
| Header etagHeader = httpResponse.getFirstHeader("ETag"); |
| operation.outStatus = status; |
| operation.inOutEtag = etagHeader != null ? etagHeader.getValue() : null; |
| operation.outBody = stream; |
| } |
| |
| private ByteArrayEntity getCompressedEntity(byte[] data) throws IOException { |
| ByteArrayEntity entity; |
| if (data.length >= MIN_GZIP_SIZE) { |
| ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(data.length / 2); |
| GZIPOutputStream gzipOutput = new GZIPOutputStream(byteOutput); |
| gzipOutput.write(data); |
| gzipOutput.close(); |
| entity = new ByteArrayEntity(byteOutput.toByteArray()); |
| } else { |
| entity = new ByteArrayEntity(data); |
| } |
| return entity; |
| } |
| |
| public static String inputStreamToString(InputStream stream) throws IOException { |
| InputStreamReader reader = new InputStreamReader(stream); |
| StringBuilder builder = new StringBuilder(); |
| char buffer[] = new char[4096]; |
| int charsRead = reader.read(buffer); |
| while (charsRead > 0) { |
| builder.append(buffer, 0, charsRead); |
| } |
| return builder.toString(); |
| } |
| } |