package com.denimgroup.threadfix.webservices.tests;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
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.io.IOUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* This class provides methods for posting GET and POST requests with optional files,
* as well as a place to put methods and data that would be useful for all REST testing.
* @author mcollins
*
*/
public abstract class BaseRestTest {
protected final Log log = LogFactory.getLog(this.getClass());
public static final String GOOD_API_KEY = "U1otLaZxwQLbsHZ2HiifYtbPwbD1H4kcNgedWVIWn0";
public static final String BAD_API_KEY = "U1otLaZxwQLbsHZ2ifYtbPwbD1H4kcNgedWVIWn0";
public static final String RESTRICTED_API_KEY = "PsjLL0KUXG8J9hkC2kpvFAGllJFPaZRskomeZiB9wSc";
public static final String BASE_URL = "http://localhost:8080/threadfix/rest";
public static final String RESTRICTED_URL_NOT_RETURNED = "The restricted URL error was not returned correctly.";
public static final String RESTRICTED_URL_RETURNED = "The restricted URL error was returned when it shouldn't have been.";
public String httpPostFile(String request, String fileName, String[] paramNames,
String[] paramVals) {
File file = new File(fileName);
return httpPostFile(request, file, paramNames,
paramVals);
}
public String httpPostFile(String request, File file, String[] paramNames,
String[] paramVals) {
Protocol.registerProtocol("https", new Protocol("https", new AcceptAllTrustFactory(), 443));
PostMethod filePost = new PostMethod(request);
filePost.setRequestHeader("Accept", "application/json");
String result = null;
InputStream responseStream = null;
try {
Part[] parts = new Part[paramNames.length + 1];
parts[paramNames.length] = new FilePart("file", file);
for (int i = 0; i < paramNames.length; i++) {
parts[i] = new StringPart(paramNames[i], paramVals[i]);
}
filePost.setRequestEntity(new MultipartRequestEntity(parts,
filePost.getParams()));
filePost.setContentChunked(true);
HttpClient client = new HttpClient();
int status = client.executeMethod(filePost);
if (status != 200) {
log.debug("Status was not 200.");
}
responseStream = filePost.getResponseBodyAsStream();
if (responseStream != null) {
result = IOUtils.toString(responseStream);
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (responseStream != null) {
try {
responseStream.close();
} catch (IOException e) {
log.warn("IOException encountered while attempting to close a stream.", e);
}
}
}
if (result == null) {
return "There was an error and the POST request was not finished.";
} else {
return result;
}
}
public String httpPost(String request, String[] paramNames,
String[] paramVals) {
Protocol.registerProtocol("https", new Protocol("https", new AcceptAllTrustFactory(), 443));
PostMethod post = new PostMethod(request);
post.setRequestHeader("Accept", "application/json");
try {
for (int i = 0; i < paramNames.length; i++) {
post.addParameter(paramNames[i], paramVals[i]);
}
HttpClient client = new HttpClient();
int status = client.executeMethod(post);
if (status != 200) {
log.debug("Status was not 200.");
}
InputStream responseStream = post.getResponseBodyAsStream();
if (responseStream != null) {
return IOUtils.toString(responseStream);
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "There was an error and the POST request was not finished.";
}
public String httpGet(String urlStr) {
log.debug("Requesting " + urlStr);
Protocol.registerProtocol("https", new Protocol("https", new AcceptAllTrustFactory(), 443));
GetMethod get = new GetMethod(urlStr);
get.setRequestHeader("Accept", "application/json");
HttpClient client = new HttpClient();
try {
int status = client.executeMethod(get);
if (status != 200) {
log.debug("Status was not 200.");
}
InputStream responseStream = get.getResponseBodyAsStream();
if (responseStream != null) {
return IOUtils.toString(responseStream);
}
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "There was an error and the GET request was not finished.";
}
/**
* Convenience method to wrap the exception catching.
* @param responseContents
* @return
*/
protected JSONObject getJSONObject(String responseContents) {
try {
return new JSONObject(responseContents);
} catch (JSONException e) {
log.warn("JSON Parsing failed.");
return null;
}
}
/**
* Convenience method to wrap the exception catching.
* @param object
* @return
*/
protected Integer getId(JSONObject object) {
try {
return object.getInt("id");
} catch (JSONException e) {
log.warn("Failed when trying to parse an ID out of the object.");
return null;
}
}
protected String getString(JSONObject object, String key) {
try {
return object.getString(key);
} catch (JSONException e) {
log.warn("Failed when trying to parse " + key + " out of a JSON object.");
return null;
}
}
protected JSONArray getJSONArray(String responseContents) {
try {
return new JSONArray(responseContents);
} catch (JSONException e) {
log.warn("JSON Parsing failed.");
return null;
}
}
/**
* This method is a wrapper for RandomStringUtils.random with a preset character set.
* @return random string
*/
protected String getRandomString(int length) {
return RandomStringUtils.random(length,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
}
/**
* These two classes allow the self-signed SSL cert to work. We might be able to cut this down.
* @author mcollins
*
*/
public class AcceptAllTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }
}
public class AcceptAllTrustFactory implements ProtocolSocketFactory {
private SSLContext sslContext = null;
private SSLContext createAcceptAllSSLContext() {
try {
AcceptAllTrustManager acceptAllTrustManager = new AcceptAllTrustManager();
SSLContext context = SSLContext.getInstance("TLS");
context.init(null,
new AcceptAllTrustManager[] { acceptAllTrustManager },
null);
return context;
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
private SSLContext getSSLContext() {
if(this.sslContext == null) {
this.sslContext = createAcceptAllSSLContext();
}
return this.sslContext;
}
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException {
return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
}
public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException {
if(params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
SocketFactory socketFactory = getSSLContext().getSocketFactory();
if(timeout == 0) {
return socketFactory.createSocket(host, port, localAddress, localPort);
}
else {
Socket socket = socketFactory.createSocket();
SocketAddress localAddr = new InetSocketAddress(localAddress, localPort);
SocketAddress remoteAddr = new InetSocketAddress(host, port);
socket.bind(localAddr);
socket.connect(remoteAddr, timeout);
return socket;
}
}
public Socket createSocket(String host, int port) throws IOException {
return getSSLContext().getSocketFactory().createSocket(host, port);
}
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
}
}