package com.bansheeproject.engine;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.SSLSocketFactory;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.OptionsMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.lang.builder.ToStringBuilder;
import com.bansheeproject.HttpHeader;
import com.bansheeproject.HttpMethod;
import com.bansheeproject.exceptions.BansheeInvocationFaultException;
import com.bansheeproject.exceptions.ServiceInvokeException;
import com.bansheeproject.features.security.CertificateCallback;
import com.bansheeproject.features.security.DefaultCertificateCallback;
import com.bansheeproject.features.security.SSLSocketFactoryGenerator;
import com.bansheeproject.log.BansheeLogger;
import com.bansheeproject.utils.IOUtils;
/**
* It is a dispatcher based on HTTP.
*
* @author Alexandre Saudate
* @since 1.0
*/
public class URLDispatcher extends BansheeDispatcher {
private String address;
private HttpMethod method;
private List<HttpHeader> headers = new ArrayList<HttpHeader>();
private HttpClient client;
private int responseCode = -1;
private String responseType = null;
public URLDispatcher(String address, HttpMethod method, HttpHeader... headers) {
this.address = address;
this.method = method;
this.client = new HttpClient();
if (headers != null) {
for (HttpHeader header : headers) {
this.headers.add(header);
}
}
}
@Override
public String invoke(String param) throws ServiceInvokeException, BansheeInvocationFaultException {
org.apache.commons.httpclient.HttpMethod method = getMethod(param, address);
try {
BansheeLogger logger = getLogger();
logger.info(param);
int responseCode = client.executeMethod(method);
String httpResponse = IOUtils.getStringFromStream(method.getResponseBodyAsStream());
//String httpResponse = new String(method.getResponseBody());
this.responseCode = responseCode;
this.responseType = method.getResponseHeader("Content-type").getValue();
boolean faultInvocation = String.valueOf(responseCode).charAt(0) == '5';
if (faultInvocation) {
logger.error(httpResponse);
throw new BansheeInvocationFaultException(httpResponse);
}
logger.info(httpResponse);
return httpResponse;
}
catch (Exception e) {
if (e instanceof BansheeInvocationFaultException) {
throw (BansheeInvocationFaultException)e;
}
throw new ServiceInvokeException(e);
}
}
public int getResponseCode() {
return responseCode;
}
public String getResponseType() {
return responseType;
}
@Override
public void invokeOneWay(String param) throws ServiceInvokeException {
org.apache.commons.httpclient.HttpMethod method = getMethod(param, address);
try {
BansheeLogger logger = getLogger();
logger.info(param);
int responseCode = client.executeMethod(method);
this.responseCode = responseCode;
String httpResponse = IOUtils.getStringFromStream(method.getResponseBodyAsStream());
boolean faultInvocation = String.valueOf(responseCode).charAt(0) == '5';
if (faultInvocation) {
logger.error(httpResponse);
throw new BansheeInvocationFaultException(httpResponse);
}
logger.info(httpResponse);
} catch (Exception e) {
throw new ServiceInvokeException(e);
}
}
public HttpClient getClient() {
return client;
}
public String getAddress() {
return address;
}
private org.apache.commons.httpclient.HttpMethod getMethod (String requestBody, String address) {
if (this.method.equals(HttpMethod.GET)) {
GetMethod get = new GetMethod(address);
return get;
}
else if (this.method.equals(HttpMethod.POST)) {
PostMethod post = new PostMethod(address);
if (requestBody != null) {
post.setRequestBody(requestBody);
}
return post;
}
else if (this.method.equals(HttpMethod.PUT)) {
PutMethod put = new PutMethod(address);
if (requestBody != null) {
put.setRequestBody(requestBody);
}
return put;
}
else if (this.method.equals(HttpMethod.DELETE)) {
DeleteMethod delete = new DeleteMethod(address);
return delete;
}
else if (this.method.equals(HttpMethod.HEAD)) {
HeadMethod head = new HeadMethod(address);
return head;
}
else if (this.method.equals(HttpMethod.OPTIONS)) {
OptionsMethod options = new OptionsMethod(address);
return options;
}
return null;
}
@Override
public void setTimeout(long timeout) {
}
@Override
public void setCertificateSelectors(String reference, InputStream keyStoreData,
String keyStorePassword, InputStream trustStoreData,
String trustStorePassword) throws GeneralSecurityException,
IOException {
setCertificateSelectors(reference, keyStoreData, keyStorePassword, trustStoreData, trustStorePassword, new DefaultCertificateCallback());
}
@Override
public void setCertificateSelectors(String reference, InputStream keyStoreData,
String keyStorePassword, InputStream trustStoreData,
String trustStorePassword, CertificateCallback callback)
throws GeneralSecurityException, IOException {
SSLSocketFactoryGenerator generator = new SSLSocketFactoryGenerator();
SSLSocketFactory socketFactory = generator.getSSLSocketFactoryInstance(reference, keyStoreData, keyStorePassword, trustStoreData, trustStorePassword, callback);
SSLProtocolSocketfactory protocolSocketfactory = new SSLProtocolSocketfactory(socketFactory);
Protocol protocol = new Protocol("https", protocolSocketfactory, 443);
Protocol.registerProtocol("https", protocol);
}
@Override
public void changeInvocationAddress(String address) {
this.address = address;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder = builder.append(this.address).append(this.responseCode);
builder = builder.append(this.responseType);
return builder.toString();
}
private class SSLProtocolSocketfactory implements ProtocolSocketFactory {
private SSLSocketFactory delegateSocketFactory;
public SSLProtocolSocketfactory(SSLSocketFactory delegate) {
this.delegateSocketFactory = delegate;
}
public Socket createSocket(String arg0, int arg1) throws IOException,
UnknownHostException {
return delegateSocketFactory.createSocket(arg0, arg1);
}
public Socket createSocket(String arg0, int arg1, InetAddress arg2,
int arg3) throws IOException, UnknownHostException {
return delegateSocketFactory.createSocket(arg0, arg1, arg2, arg3);
}
public Socket createSocket(String arg0, int arg1, InetAddress arg2,
int arg3, HttpConnectionParams arg4) throws IOException,
UnknownHostException, ConnectTimeoutException {
return delegateSocketFactory.createSocket(arg0, arg1, arg2, arg3);
}
}
}