Java tutorial
/* * Copyright (C) 2011 lightcouch.org * Copyright (c) 2015 IBM Corp. All rights reserved. * * 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.cloudant.client.org.lightcouch; import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.RequestLine; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthScope; import org.apache.http.auth.AuthState; import org.apache.http.auth.Credentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.client.protocol.ClientContext; import org.apache.http.conn.params.ConnRoutePNames; 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.conn.ssl.SSLSocketFactory; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.AbstractHttpClient; 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.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; import java.io.IOException; import java.net.Socket; import java.net.URLDecoder; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; /** * Presents a <i>client</i> to CouchDB database server; targeted to run on Android platform. * * @author Ahmed Yehia * @see CouchDbClient * @since 0.1.0 */ @SuppressWarnings("deprecation") public class CouchDbClientAndroid extends CouchDbClientBase { /** * @see CouchDbClient#CouchDbClient() */ public CouchDbClientAndroid() { super(); } /** * @see CouchDbClient#CouchDbClient(String) */ public CouchDbClientAndroid(String configFileName) { super(new CouchDbConfig(configFileName)); } /** * @see CouchDbClient#CouchDbClient(String, boolean, String, String, int, String, String) */ public CouchDbClientAndroid(String protocol, String host, int port, String username, String password) { super(new CouchDbConfig(new CouchDbProperties(protocol, host, port, username, password))); } /** * @see CouchDbClient#CouchDbClient(CouchDbProperties) */ public CouchDbClientAndroid(CouchDbProperties properties) { super(new CouchDbConfig(properties)); } /** * @return {@link DefaultHttpClient} instance. */ @Override HttpClient createHttpClient(CouchDbProperties props) { DefaultHttpClient httpclient = null; try { final SchemeRegistry schemeRegistry = createRegistry(props); // Http params final HttpParams params = new BasicHttpParams(); params.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8"); params.setParameter(CoreConnectionPNames.SO_TIMEOUT, props.getSocketTimeout()); params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, props.getConnectionTimeout()); final ThreadSafeClientConnManager ccm = new ThreadSafeClientConnManager(params, schemeRegistry); httpclient = new DefaultHttpClient(ccm, params); if (props.getProxyHost() != null) { HttpHost proxy = new HttpHost(props.getProxyHost(), props.getProxyPort()); httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } // basic authentication if (props.getUsername() != null && props.getPassword() != null) { httpclient.getCredentialsProvider().setCredentials(new AuthScope(props.getHost(), props.getPort()), new UsernamePasswordCredentials(props.getUsername(), props.getPassword())); props.clearPassword(); } registerInterceptors(httpclient); } catch (Exception e) { throw new IllegalStateException("Error Creating HTTP client. ", e); } return httpclient; } @Override HttpContext createContext() { HttpContext context = new BasicHttpContext(); BasicScheme basicAuth = new BasicScheme(); context.setAttribute("preemptive-auth", basicAuth); ((AbstractHttpClient) httpClient).addRequestInterceptor(new PreemptiveAuthInterceptor(), 0); return context; } @Override public void shutdown() { this.httpClient.getConnectionManager().shutdown(); } private SchemeRegistry createRegistry(CouchDbProperties properties) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException { SchemeRegistry registry = new SchemeRegistry(); if ("https".equals(properties.getProtocol())) { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); registry.register(new Scheme(properties.getProtocol(), sf, properties.getPort())); } else { registry.register(new Scheme(properties.getProtocol(), PlainSocketFactory.getSocketFactory(), properties.getPort())); } return registry; } private void registerInterceptors(DefaultHttpClient httpclient) { httpclient.addRequestInterceptor(new HttpRequestInterceptor() { public void process(final HttpRequest request, final HttpContext context) throws IOException { if (log.isInfoEnabled()) { RequestLine req = request.getRequestLine(); log.info("> " + req.getMethod() + URLDecoder.decode(req.getUri(), "UTF-8")); } } }); httpclient.addResponseInterceptor(new HttpResponseInterceptor() { public void process(final HttpResponse response, final HttpContext context) throws IOException { if (log.isInfoEnabled()) { log.info("< Status: " + response.getStatusLine().getStatusCode()); } validate(response); } }); } private static class MySSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; sslContext.init(null, new TrustManager[] { tm }, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } private static class PreemptiveAuthInterceptor implements HttpRequestInterceptor { public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); // If no auth scheme avaialble yet, try to initialize it preemptively if (authState.getAuthScheme() == null) { AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth"); CredentialsProvider credsProvider = (CredentialsProvider) context .getAttribute(ClientContext.CREDS_PROVIDER); HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST); if (authScheme != null) { authState.setAuthScheme(authScheme); Credentials creds = credsProvider .getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort())); if (creds != null) { authState.setCredentials(creds); } } } } } @Override CouchDatabaseBase database(String name, boolean create) { return new CouchDatabase(this, name, create); } }