/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.web.analytics.push;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.MediaType;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.opengamma.util.tuple.ObjectsPair;
import com.opengamma.util.tuple.Pair;
public class WebPushTestUtils {
/**
* The port to use, or {@code 0} if none has been agreed yet.
*/
private int _port;
private String _urlBase;
public WebPushTestUtils() {
}
public WebPushTestUtils(final int port) {
setPort(port);
}
private void setPort(final int port) {
_port = port;
_urlBase = "http://localhost:" + port;
}
/* package */ URL url(final String path) throws MalformedURLException {
return new URL(_urlBase + path);
}
/* package */ public String readFromPath(final String path) throws IOException {
return readFromPath(path, null);
}
/* package */ public String readFromPath(final String path, final String clientId) throws IOException {
return readFromPath(path, clientId, "GET");
}
/* package */
public String handshake() throws IOException {
final String json = readFromPath("/handshake");
try {
return new JSONObject(json).getString("clientId");
} catch (final JSONException e) {
throw new IllegalArgumentException("Failed to create JSON from handshake response: " + json, e);
}
}
/* package */ String readFromPath(final String path, final String clientId, final String requestMethod) throws IOException {
String fullPath;
if (clientId != null) {
fullPath = path + "?clientId=" + clientId;
} else {
fullPath = path;
}
BufferedReader reader = null;
HttpURLConnection connection = null;
StringBuilder builder;
try {
final char[] chars = new char[512];
builder = new StringBuilder();
final URL url = url(fullPath);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(requestMethod);
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
int bytesRead;
while ((bytesRead = reader.read(chars)) != -1) {
builder.append(chars, 0, bytesRead);
}
} finally {
if (reader != null) {
reader.close();
}
if (connection != null) {
connection.disconnect();
}
}
return builder.toString();
}
public HttpURLConnection connectToPath(final String path) throws IOException {
final URL url = url(path);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
return connection;
}
public static String readAndClose(final HttpURLConnection connection) throws IOException {
BufferedReader reader = null;
StringBuilder builder;
try {
final char[] chars = new char[512];
builder = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
int bytesRead;
while ((bytesRead = reader.read(chars)) != -1) {
builder.append(chars, 0, bytesRead);
}
} finally {
if (reader != null) {
reader.close();
}
if (connection != null) {
connection.disconnect();
}
}
return builder.toString();
}
/**
* Creates and starts a Jetty server using {@code web-push/WEB-INF/web.xml} and configured using Spring
* @return The server and the Spring context
* @param springXml The location of the Spring XML config file
*/
public Pair<Server, WebApplicationContext> createJettyServer(final String springXml) throws Exception {
final WebAppContext context = new WebAppContext();
context.setContextPath("/");
context.setResourceBase("build/classes");
context.setDescriptor("web-push/WEB-INF/web.xml");
context.setInitParameter("contextConfigLocation", springXml);
context.addEventListener(new ContextLoaderListener());
final Server server = new Server();
server.setHandler(context);
final SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(_port);
server.addConnector(connector);
server.start();
if (_port == 0) {
setPort(connector.getLocalPort());
}
final Context servletContext = context.getServletContext();
final WebApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
final Map<String, ConnectionManager> cmMap = springContext.getBeansOfType(ConnectionManager.class);
if (cmMap.size() == 1) {
WebPushServletContextUtils.setConnectionManager(servletContext, cmMap.values().iterator().next());
}
final Map<String, LongPollingConnectionManager> lpcmMap = springContext.getBeansOfType(LongPollingConnectionManager.class);
if (lpcmMap.size() == 1) {
WebPushServletContextUtils.setLongPollingConnectionManager(servletContext, lpcmMap.values().iterator().next());
}
return new ObjectsPair<Server, WebApplicationContext>(server, springContext);
}
/**
* Asserts that {@code json} represents a JSON object with a field called {@code updates} whose value is an array
* of the expected values.
* @param json {@code {updates: [url1, url2, ...]}}
* @param urls URLs that must be present in the JSON
*/
static void checkJsonResults(final String json, final String... urls) throws JSONException {
final List<String> expectedList = Arrays.asList(urls);
final JSONArray results = new JSONObject(json).getJSONArray(LongPollingUpdateListener.UPDATES);
assertEquals("Wrong number of results. expected: " + expectedList + ", actual: " + results, expectedList.size(), results.length());
for (int i = 0; i < results.length(); i++) {
final String result = results.getString(i);
assertTrue("Unexpected result: " + result, expectedList.contains(result));
}
}
/**
* @return The URL of the viewport relative to the root
*/
public String createViewport(final String clientId, final String viewportDefJson) throws IOException, JSONException {
String viewportJson;
BufferedReader reader = null;
BufferedWriter writer = null;
try {
final URL url = new URL("http://localhost:" + _port + "/jax/viewports?clientId=" + clientId);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("CONTENT-TYPE", MediaType.APPLICATION_JSON);
connection.connect();
writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.write(viewportDefJson);
writer.flush();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
viewportJson = reader.readLine();
} finally {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
}
return new JSONObject(viewportJson).getString("viewportUrl");
}
}