@ -15,13 +15,16 @@
* along with Transdroid . If not , see < http : //www.gnu.org/licenses/>.
* along with Transdroid . If not , see < http : //www.gnu.org/licenses/>.
*
*
* /
* /
package org.transdroid.daemon.util ;
package org.transdroid.daemon.util ;
import java.io.BufferedReader ;
import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.io.InputStreamReader ;
import java.io.UnsupportedEncodingException ;
import java.io.UnsupportedEncodingException ;
import java.util.Collections ;
import java.util.HashMap ;
import java.util.Map ;
import java.util.zip.GZIPInputStream ;
import java.util.zip.GZIPInputStream ;
import org.apache.http.Header ;
import org.apache.http.Header ;
@ -51,11 +54,11 @@ import org.transdroid.daemon.DaemonException;
import org.transdroid.daemon.DaemonException.ExceptionType ;
import org.transdroid.daemon.DaemonException.ExceptionType ;
import org.transdroid.daemon.DaemonSettings ;
import org.transdroid.daemon.DaemonSettings ;
import android.net.Uri ;
/ * *
/ * *
* Provides a set of general helper methods that can be used in web - based communication .
* Provides a set of general helper methods that can be used in web - based communication .
*
* @author erickok
* @author erickok
*
* /
* /
public class HttpHelper {
public class HttpHelper {
@ -71,19 +74,22 @@ public class HttpHelper {
public static String userAgent = null ;
public static String userAgent = null ;
/ * *
/ * *
* Creates a standard Apache HttpClient that is thread safe , supports different
* Creates a standard Apache HttpClient that is thread safe , supports different SSL auth methods and basic
* SSL auth methods and basic authentication
* authentication
* @param settings The server settings to adhere
* @param settings The server settings to adhere
* @return An HttpClient that should be stored locally and reused for every new request
* @return An HttpClient that should be stored locally and reused for every new request
* @throws DaemonException Thrown when information ( such as username / password ) is missing
* @throws DaemonException Thrown when information ( such as username / password ) is missing
* /
* /
public static DefaultHttpClient createStandardHttpClient ( DaemonSettings settings , boolean userBasicAuth ) throws DaemonException {
public static DefaultHttpClient createStandardHttpClient ( DaemonSettings settings , boolean userBasicAuth )
return createStandardHttpClient ( userBasicAuth & & settings . shouldUseAuthentication ( ) , settings . getUsername ( ) , settings . getPassword ( ) , settings . getSslTrustAll ( ) , settings . getSslTrustKey ( ) , settings . getTimeoutInMilliseconds ( ) , settings . getAddress ( ) , settings . getPort ( ) ) ;
throws DaemonException {
return createStandardHttpClient ( userBasicAuth & & settings . shouldUseAuthentication ( ) , settings . getUsername ( ) ,
settings . getPassword ( ) , settings . getSslTrustAll ( ) , settings . getSslTrustKey ( ) ,
settings . getTimeoutInMilliseconds ( ) , settings . getAddress ( ) , settings . getPort ( ) ) ;
}
}
/ * *
/ * *
* Creates a standard Apache HttpClient that is thread safe , supports different
* Creates a standard Apache HttpClient that is thread safe , supports different SSL auth methods and basic
* SSL auth methods and basic authentication
* authentication
* @param sslTrustAll Whether to trust all SSL certificates
* @param sslTrustAll Whether to trust all SSL certificates
* @param sslTrustkey A specific SSL key to accept exclusively
* @param sslTrustkey A specific SSL key to accept exclusively
* @param timeout The connection timeout for all requests
* @param timeout The connection timeout for all requests
@ -92,13 +98,15 @@ public class HttpHelper {
* @return An HttpClient that should be stored locally and reused for every new request
* @return An HttpClient that should be stored locally and reused for every new request
* @throws DaemonException Thrown when information ( such as username / password ) is missing
* @throws DaemonException Thrown when information ( such as username / password ) is missing
* /
* /
public static DefaultHttpClient createStandardHttpClient ( boolean userBasicAuth , String username , String password , boolean sslTrustAll , String sslTrustkey , int timeout , String authAddress , int authPort ) throws DaemonException {
public static DefaultHttpClient createStandardHttpClient ( boolean userBasicAuth , String username , String password ,
boolean sslTrustAll , String sslTrustkey , int timeout , String authAddress , int authPort )
throws DaemonException {
// Register http and https sockets
// Register http and https sockets
SchemeRegistry registry = new SchemeRegistry ( ) ;
SchemeRegistry registry = new SchemeRegistry ( ) ;
registry . register ( new Scheme ( "http" , new PlainSocketFactory ( ) , 80 ) ) ;
registry . register ( new Scheme ( "http" , new PlainSocketFactory ( ) , 80 ) ) ;
SocketFactory https_socket = sslTrustAll ? new FakeSocketFactory ( )
SocketFactory https_socket = sslTrustAll ? new FakeSocketFactory ( )
: sslTrustkey ! = null ? new FakeSocketFactory ( sslTrustkey ) : SSLSocketFactory . getSocketFactory ( ) ;
: sslTrustkey ! = null ? new FakeSocketFactory ( sslTrustkey ) : SSLSocketFactory . getSocketFactory ( ) ;
registry . register ( new Scheme ( "https" , https_socket , 443 ) ) ;
registry . register ( new Scheme ( "https" , https_socket , 443 ) ) ;
// Standard parameters
// Standard parameters
@ -109,16 +117,18 @@ public class HttpHelper {
HttpProtocolParams . setUserAgent ( httpparams , userAgent ) ;
HttpProtocolParams . setUserAgent ( httpparams , userAgent ) ;
}
}
DefaultHttpClient httpclient = new DefaultHttpClient ( new ThreadSafeClientConnManager ( httpparams , registry ) , httpparams ) ;
DefaultHttpClient httpclient = new DefaultHttpClient ( new ThreadSafeClientConnManager ( httpparams , registry ) ,
httpparams ) ;
// Authentication credentials
// Authentication credentials
if ( userBasicAuth ) {
if ( userBasicAuth ) {
if ( username = = null | | password = = null ) {
if ( username = = null | | password = = null ) {
throw new DaemonException ( ExceptionType . AuthenticationFailure , "No username or password was provided while we hadauthentication enabled" ) ;
throw new DaemonException ( ExceptionType . AuthenticationFailure ,
"No username or password was provided while we hadauthentication enabled" ) ;
}
}
httpclient . getCredentialsProvider ( ) . setCredentials (
httpclient . getCredentialsProvider ( ) . setCredentials (
new AuthScope ( authAddress , authPort , AuthScope . ANY_REALM ) ,
new AuthScope ( authAddress , authPort , AuthScope . ANY_REALM ) ,
new UsernamePasswordCredentials ( username , password ) ) ;
new UsernamePasswordCredentials ( username , password ) ) ;
}
}
return httpclient ;
return httpclient ;
@ -129,103 +139,132 @@ public class HttpHelper {
* HTTP request interceptor to allow for GZip - encoded data transfer
* HTTP request interceptor to allow for GZip - encoded data transfer
* /
* /
public static HttpRequestInterceptor gzipRequestInterceptor = new HttpRequestInterceptor ( ) {
public static HttpRequestInterceptor gzipRequestInterceptor = new HttpRequestInterceptor ( ) {
public void process ( final HttpRequest request , final HttpContext context ) throws HttpException , IOException {
public void process ( final HttpRequest request , final HttpContext context ) throws HttpException , IOException {
if ( ! request . containsHeader ( "Accept-Encoding" ) ) {
if ( ! request . containsHeader ( "Accept-Encoding" ) ) {
request . addHeader ( "Accept-Encoding" , "gzip" ) ;
request . addHeader ( "Accept-Encoding" , "gzip" ) ;
}
}
}
}
} ;
} ;
/ * *
/ * *
* HTTP response interceptor that decodes GZipped data
* HTTP response interceptor that decodes GZipped data
* /
* /
public static HttpResponseInterceptor gzipResponseInterceptor = new HttpResponseInterceptor ( ) {
public static HttpResponseInterceptor gzipResponseInterceptor = new HttpResponseInterceptor ( ) {
public void process ( final HttpResponse response , final HttpContext context ) throws HttpException , IOException {
public void process ( final HttpResponse response , final HttpContext context ) throws HttpException , IOException {
HttpEntity entity = response . getEntity ( ) ;
HttpEntity entity = response . getEntity ( ) ;
Header ceheader = entity . getContentEncoding ( ) ;
Header ceheader = entity . getContentEncoding ( ) ;
if ( ceheader ! = null ) {
if ( ceheader ! = null ) {
HeaderElement [ ] codecs = ceheader . getElements ( ) ;
HeaderElement [ ] codecs = ceheader . getElements ( ) ;
for ( int i = 0 ; i < codecs . length ; i + + ) {
for ( int i = 0 ; i < codecs . length ; i + + ) {
if ( codecs [ i ] . getName ( ) . equalsIgnoreCase ( "gzip" ) ) {
if ( codecs [ i ] . getName ( ) . equalsIgnoreCase ( "gzip" ) ) {
response . setEntity ( new HttpHelper . GzipDecompressingEntity ( response . getEntity ( ) ) ) ;
response . setEntity ( new HttpHelper . GzipDecompressingEntity ( response . getEntity ( ) ) ) ;
return ;
return ;
}
}
}
}
}
}
}
}
} ;
} ;
/ * *
/ * *
* HTTP entity wrapper to decompress GZipped HTTP responses
* HTTP entity wrapper to decompress GZipped HTTP responses
* /
* /
private static class GzipDecompressingEntity extends HttpEntityWrapper {
private static class GzipDecompressingEntity extends HttpEntityWrapper {
public GzipDecompressingEntity ( final HttpEntity entity ) {
public GzipDecompressingEntity ( final HttpEntity entity ) {
super ( entity ) ;
super ( entity ) ;
}
}
@Override
public InputStream getContent ( ) throws IOException , IllegalStateException {
@Override
// the wrapped entity's getContent() decides about repeatability
public InputStream getContent ( ) throws IOException , IllegalStateException {
InputStream wrappedin = wrappedEntity . getContent ( ) ;
return new GZIPInputStream ( wrappedin ) ;
}
// the wrapped entity's getContent() decides about repeatability
@Override
InputStream wrappedin = wrappedEntity . getContent ( ) ;
public long getContentLength ( ) {
// length of ungzipped content is not known
return - 1 ;
}
return new GZIPInputStream ( wrappedin ) ;
}
}
@Override
/ *
public long getContentLength ( ) {
* To convert the InputStream to String we use the BufferedReader . readLine ( ) method . We iterate until the
// length of ungzipped content is not known
* BufferedReader return null which means there ' s no more data to read . Each line will appended to a StringBuilder
return - 1 ;
* and returned as String .
}
*
* Taken from http : //senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/
* /
public static String convertStreamToString ( InputStream is , String encoding ) throws UnsupportedEncodingException {
InputStreamReader isr ;
if ( encoding ! = null ) {
isr = new InputStreamReader ( is , encoding ) ;
} else {
isr = new InputStreamReader ( is ) ;
}
BufferedReader reader = new BufferedReader ( isr ) ;
StringBuilder sb = new StringBuilder ( ) ;
String line = null ;
try {
while ( ( line = reader . readLine ( ) ) ! = null ) {
sb . append ( line + "\n" ) ;
}
} catch ( IOException e ) {
e . printStackTrace ( ) ;
} finally {
try {
is . close ( ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
return sb . toString ( ) ;
}
}
/ *
public static String convertStreamToString ( InputStream is ) {
* To convert the InputStream to String we use the BufferedReader . readLine ( )
try {
* method . We iterate until the BufferedReader return null which means
return convertStreamToString ( is , null ) ;
* there ' s no more data to read . Each line will appended to a StringBuilder
* and returned as String .
*
* Taken from http : //senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-restful-client-at-android/
* /
public static String ConvertStreamToString ( InputStream is , String encoding ) throws UnsupportedEncodingException {
InputStreamReader isr ;
if ( encoding ! = null ) {
isr = new InputStreamReader ( is , encoding ) ;
} else {
isr = new InputStreamReader ( is ) ;
}
BufferedReader reader = new BufferedReader ( isr ) ;
StringBuilder sb = new StringBuilder ( ) ;
String line = null ;
try {
while ( ( line = reader . readLine ( ) ) ! = null ) {
sb . append ( line + "\n" ) ;
}
} catch ( IOException e ) {
e . printStackTrace ( ) ;
} finally {
try {
is . close ( ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
return sb . toString ( ) ;
}
public static String ConvertStreamToString ( InputStream is ) {
try {
return ConvertStreamToString ( is , null ) ;
} catch ( UnsupportedEncodingException e ) {
} catch ( UnsupportedEncodingException e ) {
// Since this is going to use the default encoding, it is never going to crash on an UnsupportedEncodingException
// Since this is going to use the default encoding, it is never going to crash on an
// UnsupportedEncodingException
e . printStackTrace ( ) ;
e . printStackTrace ( ) ;
return null ;
return null ;
}
}
}
}
/ * *
* Parses the individual parameters from a textual cookie representation - like string and returns them in an unsorted
* map . Inspired by Android ' s ( API level 11 + ) getQueryParameterNames ( Uri ) .
* @param raw A string of the form key1 = value1 ; key2 = value
* @return An unsorted , unmodifiable map of pairs of string keys and string values
* /
public static Map < String , String > parseCookiePairs ( String raw ) {
Map < String , String > pairs = new HashMap < String , String > ( ) ;
int start = 0 ;
do {
int next = raw . indexOf ( ';' , start ) ;
int end = ( next = = - 1 ) ? raw . length ( ) : next ;
int separator = raw . indexOf ( '=' , start ) ;
if ( separator > end | | separator = = - 1 ) {
separator = end ;
}
String name = raw . substring ( start , separator ) ;
String value = raw . substring ( separator + 1 , end ) ;
pairs . put ( Uri . decode ( name ) , Uri . decode ( value ) ) ;
start = end + 1 ;
} while ( start < raw . length ( ) ) ;
return Collections . unmodifiableMap ( pairs ) ;
}
}
}