/*******************************************************************************
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* Contributors:
* Gregory Amerson - initial implementation and ongoing maintenance
*******************************************************************************/
package com.liferay.ide.core.remote;
import com.liferay.ide.core.LiferayCore;
import com.liferay.ide.core.util.CoreUtil;
import com.liferay.ide.core.util.StringPool;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
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.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.core.net.proxy.IProxyService;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Gregory Amerson
* @author Tao Tao
* @author Terry Jia
*/
public class RemoteConnection implements IRemoteConnection
{
private String hostname;
private HttpClient httpClient;
private int httpPort;
private String password;
private String username;
protected Object deleteJSONAPI( Object... args ) throws APIException
{
if( !( args[0] instanceof String ) )
{
throw new IllegalArgumentException( "First argument must be a string." ); //$NON-NLS-1$
}
HttpDelete deleteAPIMethod = new HttpDelete();
return httpJSONAPI( deleteAPIMethod, args );
}
public String getHost()
{
return hostname;
}
private HttpClient getHttpClient()
{
if( this.httpClient == null )
{
DefaultHttpClient newDefaultHttpClient = null;
if( getUsername() != null || getPassword() != null )
{
try
{
final IProxyService proxyService = LiferayCore.getProxyService();
URI uri = new URI( "http://" + getHost() + ":" + getHttpPort() ); //$NON-NLS-1$ //$NON-NLS-2$
IProxyData[] proxyDataForHost = proxyService.select( uri );
for( IProxyData data : proxyDataForHost )
{
if( data.getHost() != null && data.getPort() > 0 )
{
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register( new Scheme(
"http", data.getPort(), PlainSocketFactory.getSocketFactory() ) ); //$NON-NLS-1$
PoolingClientConnectionManager cm = new PoolingClientConnectionManager( schemeRegistry );
cm.setMaxTotal( 200 );
cm.setDefaultMaxPerRoute( 20 );
DefaultHttpClient newHttpClient = new DefaultHttpClient( cm );
HttpHost proxy = new HttpHost( data.getHost(), data.getPort() );
newHttpClient.getParams().setParameter( ConnRoutePNames.DEFAULT_PROXY, proxy );
newDefaultHttpClient = newHttpClient;
break;
}
}
if( newDefaultHttpClient == null )
{
uri = new URI( "SOCKS://" + getHost() + ":" + getHttpPort() ); //$NON-NLS-1$ //$NON-NLS-2$
proxyDataForHost = proxyService.select( uri );
for( IProxyData data : proxyDataForHost )
{
if( data.getHost() != null )
{
DefaultHttpClient newHttpClient = new DefaultHttpClient();
newHttpClient.getParams().setParameter( "socks.host", data.getHost() ); //$NON-NLS-1$
newHttpClient.getParams().setParameter( "socks.port", data.getPort() ); //$NON-NLS-1$
newHttpClient.getConnectionManager().getSchemeRegistry().register(
new Scheme( "socks", data.getPort(), PlainSocketFactory.getSocketFactory() ) ); //$NON-NLS-1$
newDefaultHttpClient = newHttpClient;
break;
}
}
}
}
catch( URISyntaxException e )
{
LiferayCore.logError( "Unable to read proxy data", e ); //$NON-NLS-1$
}
if( newDefaultHttpClient == null )
{
newDefaultHttpClient = new DefaultHttpClient();
}
this.httpClient = newDefaultHttpClient;
}
else
{
this.httpClient = new DefaultHttpClient();
}
}
return this.httpClient;
}
public int getHttpPort()
{
return httpPort;
}
protected String getHttpResponse( HttpUriRequest request ) throws Exception
{
if( !CoreUtil.isNullOrEmpty( getUsername() ) && !CoreUtil.isNullOrEmpty( getPassword() ) )
{
String encoding = getUsername() + ":" + getPassword();
request.setHeader( "Authorization", "Basic " + Base64.encodeBase64String( encoding.getBytes() ) );
}
HttpResponse response = getHttpClient().execute( request );
int statusCode = response.getStatusLine().getStatusCode();
if( statusCode == HttpStatus.SC_OK )
{
HttpEntity entity = response.getEntity();
String body = CoreUtil.readStreamToString( entity.getContent(), false );
EntityUtils.consume( entity );
return body;
}
else
{
return response.getStatusLine().getReasonPhrase();
}
}
protected Object getJSONAPI( Object... args ) throws APIException
{
if( !( args[0] instanceof String ) )
{
throw new IllegalArgumentException( "First argument must be a string." ); //$NON-NLS-1$
}
HttpGet getAPIMethod = new HttpGet();
return httpJSONAPI( getAPIMethod, args );
}
private Object getJSONResponse( String response )
{
Object retval = null;
try
{
retval = new JSONObject( response );
}
catch( JSONException e )
{
try
{
retval = new JSONArray( response );
}
catch( JSONException e1 )
{
}
}
return retval;
}
public String getPassword()
{
return password;
}
public String getUsername()
{
return username;
}
protected Object httpJSONAPI( Object... args ) throws APIException
{
if( !( args[0] instanceof HttpRequestBase ) )
{
throw new IllegalArgumentException( "First argument must be a HttpRequestBase." ); //$NON-NLS-1$
}
Object retval = null;
String api = null;
Object[] params = new Object[0];
final HttpRequestBase request = (HttpRequestBase) args[0];
final boolean isPostRequest = request instanceof HttpPost;
if( args[1] instanceof String )
{
api = args[1].toString();
}
else if( args[1] instanceof Object[] )
{
params = (Object[]) args[1];
api = params[0].toString();
}
else
{
throw new IllegalArgumentException( "2nd argument must be either String or Object[]" ); //$NON-NLS-1$
}
try
{
final URIBuilder builder = new URIBuilder();
builder.setScheme( "http" ); //$NON-NLS-1$
builder.setHost( getHost() );
builder.setPort( getHttpPort() );
builder.setPath( api );
List<NameValuePair> postParams = new ArrayList<NameValuePair>();
if( params.length >= 3 )
{
for( int i = 1; i < params.length; i += 2 )
{
String name = null;
String value = StringPool.EMPTY;
if( params[i] != null )
{
name = params[i].toString();
}
if( params[i + 1] != null )
{
value = params[i + 1].toString();
}
if( isPostRequest )
{
postParams.add( new BasicNameValuePair( name, value ) );
}
else
{
builder.setParameter( name, value );
}
}
}
if( isPostRequest )
{
HttpPost postRequest = ( (HttpPost) request );
if( postRequest.getEntity() == null )
{
postRequest.setEntity( new UrlEncodedFormEntity( postParams ) );
}
}
request.setURI( builder.build() );
String response = getHttpResponse( request );
if( response != null && response.length() > 0 )
{
Object jsonResponse = getJSONResponse( response );
if( jsonResponse == null )
{
throw new APIException( api, "Unable to get response: " + response ); //$NON-NLS-1$
}
else
{
retval = jsonResponse;
}
}
}
catch( APIException e )
{
throw e;
}
catch( Exception e )
{
throw new APIException( api, e );
}
finally
{
try
{
request.releaseConnection();
}
finally
{
// no need to log error
}
}
return retval;
}
protected Object postJSONAPI( Object... args ) throws APIException
{
if( !( args[0] instanceof String ) )
{
throw new IllegalArgumentException( "First argument must be a string." ); //$NON-NLS-1$
}
HttpPost post = new HttpPost();
return httpJSONAPI( post, args );
}
public void setHost( String host )
{
this.hostname = host;
releaseHttpClient();
}
public void setHttpPort( String httpPort )
{
if( httpPort != null )
{
this.httpPort = Integer.parseInt( httpPort );
}
else
{
this.httpPort = -1;
}
releaseHttpClient();
}
public void setPassword( String password )
{
this.password = password;
releaseHttpClient();
}
public void setUsername( String username )
{
this.username = username;
releaseHttpClient();
}
public void releaseHttpClient()
{
if( httpClient != null )
{
this.httpClient.getConnectionManager().shutdown();
this.httpClient = null;
}
}
}