mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
231 lines
8.7 KiB
Java
231 lines
8.7 KiB
Java
|
/* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (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.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is Android Sync Client.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* the Mozilla Foundation.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
* Richard Newman <rnewman@mozilla.com>
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
|
* of those above. If you wish to allow use of your version of this file only
|
||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
|
* use your version of this file under the terms of the MPL, indicate your
|
||
|
* decision by deleting the provisions above and replace them with the notice
|
||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
|
* the provisions above, a recipient may use your version of this file under
|
||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
package org.mozilla.gecko.sync.net;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.net.URI;
|
||
|
import java.net.URISyntaxException;
|
||
|
import java.security.KeyManagementException;
|
||
|
import java.security.NoSuchAlgorithmException;
|
||
|
import java.security.SecureRandom;
|
||
|
|
||
|
import javax.net.ssl.SSLContext;
|
||
|
|
||
|
import android.util.Log;
|
||
|
import ch.boye.httpclientandroidlib.Header;
|
||
|
import ch.boye.httpclientandroidlib.HttpEntity;
|
||
|
import ch.boye.httpclientandroidlib.HttpResponse;
|
||
|
import ch.boye.httpclientandroidlib.auth.Credentials;
|
||
|
import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials;
|
||
|
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
|
||
|
import ch.boye.httpclientandroidlib.client.methods.HttpDelete;
|
||
|
import ch.boye.httpclientandroidlib.client.methods.HttpGet;
|
||
|
import ch.boye.httpclientandroidlib.client.methods.HttpPost;
|
||
|
import ch.boye.httpclientandroidlib.client.methods.HttpPut;
|
||
|
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
|
||
|
import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
|
||
|
import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
|
||
|
import ch.boye.httpclientandroidlib.conn.scheme.PlainSocketFactory;
|
||
|
import ch.boye.httpclientandroidlib.conn.scheme.Scheme;
|
||
|
import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
|
||
|
import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory;
|
||
|
import ch.boye.httpclientandroidlib.impl.auth.BasicScheme;
|
||
|
import ch.boye.httpclientandroidlib.impl.client.AbstractHttpClient;
|
||
|
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
|
||
|
import ch.boye.httpclientandroidlib.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||
|
import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
|
||
|
import ch.boye.httpclientandroidlib.params.HttpParams;
|
||
|
import ch.boye.httpclientandroidlib.protocol.BasicHttpContext;
|
||
|
import ch.boye.httpclientandroidlib.protocol.HttpContext;
|
||
|
|
||
|
/**
|
||
|
* Provide simple HTTP access to a Sync server or similar.
|
||
|
* Implements Basic Auth by asking its delegate for credentials.
|
||
|
* Communicates with a ResourceDelegate to asynchronously return responses and errors.
|
||
|
* Exposes simple get/post/put/delete methods.
|
||
|
*/
|
||
|
public class BaseResource implements Resource {
|
||
|
private static final String LOG_TAG = "BaseResource";
|
||
|
protected URI uri;
|
||
|
protected BasicHttpContext context;
|
||
|
protected DefaultHttpClient client;
|
||
|
public ResourceDelegate delegate;
|
||
|
protected HttpRequestBase request;
|
||
|
|
||
|
public BaseResource(String uri) throws URISyntaxException {
|
||
|
this(new URI(uri));
|
||
|
}
|
||
|
public BaseResource(URI uri) {
|
||
|
this.uri = uri;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Apply the provided credentials string to the provided request.
|
||
|
* @param credentials
|
||
|
* A string, "user:pass".
|
||
|
* @param client
|
||
|
* @param request
|
||
|
* @param context
|
||
|
*/
|
||
|
private static void applyCredentials(String credentials, AbstractHttpClient client, HttpUriRequest request, HttpContext context) {
|
||
|
Credentials creds = new UsernamePasswordCredentials(credentials);
|
||
|
Header header = BasicScheme.authenticate(creds, "US-ASCII", false);
|
||
|
request.addHeader(header);
|
||
|
Log.d(LOG_TAG, "Adding auth header " + header);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Invoke this after delegate and request have been set.
|
||
|
* @throws NoSuchAlgorithmException
|
||
|
* @throws KeyManagementException
|
||
|
*/
|
||
|
private void prepareClient() throws KeyManagementException, NoSuchAlgorithmException {
|
||
|
ClientConnectionManager connectionManager = getConnectionManager();
|
||
|
context = new BasicHttpContext();
|
||
|
client = new DefaultHttpClient(connectionManager);
|
||
|
|
||
|
// TODO: Eventually we should use Apache HttpAsyncClient. It's not out of alpha yet.
|
||
|
// Until then, we synchronously make the request, then invoke our delegate's callback.
|
||
|
String credentials = delegate.getCredentials();
|
||
|
if (credentials != null) {
|
||
|
BaseResource.applyCredentials(credentials, client, request, context);
|
||
|
}
|
||
|
|
||
|
HttpParams params = client.getParams();
|
||
|
HttpConnectionParams.setConnectionTimeout(params, delegate.connectionTimeout());
|
||
|
HttpConnectionParams.setSoTimeout(params, delegate.socketTimeout());
|
||
|
delegate.addHeaders(request, client);
|
||
|
}
|
||
|
|
||
|
private static Object connManagerMonitor = new Object();
|
||
|
private static ClientConnectionManager connManager;
|
||
|
|
||
|
/**
|
||
|
* This method exists for test code.
|
||
|
* @return
|
||
|
*/
|
||
|
public static ClientConnectionManager enablePlainHTTPConnectionManager() {
|
||
|
synchronized (connManagerMonitor) {
|
||
|
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager();
|
||
|
connManager = cm;
|
||
|
return cm;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static ClientConnectionManager enableTLSConnectionManager() throws KeyManagementException, NoSuchAlgorithmException {
|
||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||
|
sslContext.init(null, null, new SecureRandom());
|
||
|
SSLSocketFactory sf = new TLSSocketFactory(sslContext);
|
||
|
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||
|
schemeRegistry.register(new Scheme("https", 443, sf));
|
||
|
schemeRegistry.register(new Scheme("http", 80, new PlainSocketFactory()));
|
||
|
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(
|
||
|
schemeRegistry);
|
||
|
connManager = cm;
|
||
|
return cm;
|
||
|
}
|
||
|
|
||
|
public static ClientConnectionManager getConnectionManager() throws KeyManagementException, NoSuchAlgorithmException
|
||
|
{
|
||
|
// TODO: shutdown.
|
||
|
synchronized (connManagerMonitor) {
|
||
|
if (connManager != null) {
|
||
|
return connManager;
|
||
|
}
|
||
|
return enableTLSConnectionManager();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void execute() {
|
||
|
try {
|
||
|
HttpResponse response = client.execute(request, context);
|
||
|
Log.i(LOG_TAG, "Response: " + response.getStatusLine().toString());
|
||
|
delegate.handleHttpResponse(response);
|
||
|
} catch (ClientProtocolException e) {
|
||
|
delegate.handleHttpProtocolException(e);
|
||
|
} catch (IOException e) {
|
||
|
delegate.handleHttpIOException(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void go(HttpRequestBase request) {
|
||
|
if (delegate == null) {
|
||
|
throw new IllegalArgumentException("No delegate provided.");
|
||
|
}
|
||
|
this.request = request;
|
||
|
try {
|
||
|
this.prepareClient();
|
||
|
} catch (KeyManagementException e) {
|
||
|
Log.e(LOG_TAG, "Couldn't prepare client.", e);
|
||
|
delegate.handleTransportException(e);
|
||
|
} catch (NoSuchAlgorithmException e) {
|
||
|
Log.e(LOG_TAG, "Couldn't prepare client.", e);
|
||
|
delegate.handleTransportException(e);
|
||
|
}
|
||
|
this.execute();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void get() {
|
||
|
Log.i(LOG_TAG, "HTTP GET " + this.uri.toASCIIString());
|
||
|
this.go(new HttpGet(this.uri));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void delete() {
|
||
|
Log.i(LOG_TAG, "HTTP DELETE " + this.uri.toASCIIString());
|
||
|
this.go(new HttpDelete(this.uri));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void post(HttpEntity body) {
|
||
|
Log.i(LOG_TAG, "HTTP POST " + this.uri.toASCIIString());
|
||
|
HttpPost request = new HttpPost(this.uri);
|
||
|
request.setEntity(body);
|
||
|
this.go(request);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void put(HttpEntity body) {
|
||
|
Log.i(LOG_TAG, "HTTP PUT " + this.uri.toASCIIString());
|
||
|
HttpPut request = new HttpPut(this.uri);
|
||
|
request.setEntity(body);
|
||
|
this.go(request);
|
||
|
}
|
||
|
}
|