/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* This samples uses multiple threads to post synchronous requests to the
* VoltDB server, simulating multiple client application posting
* synchronous requests to the database, using the native VoltDB client
* library.
*
* While synchronous processing can cause performance bottlenecks (each
* caller waits for a transaction answer before calling another
* transaction), the VoltDB cluster at large is still able to perform at
* blazing speeds when many clients are connected to it.
*/
package kvbench;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.json_voltpatches.JSONArray;
import org.json_voltpatches.JSONException;
import org.json_voltpatches.JSONObject;
import org.voltdb.ParameterSet;
import org.voltdb.VoltTable;
import org.voltdb.utils.Encoder;
public class HTTPUtils {
static class Response {
public byte status = 0;
public String statusString = null;
public byte appStatus = Byte.MIN_VALUE;
public String appStatusString = null;
public VoltTable[] results = new VoltTable[0];
public String exception = null;
}
static String username = null;
static String password = null;
static boolean prehash = true;
static void dumpResponse(Response resp) {
System.out.println("resp.toString(): " + resp.toString());
System.out.println("status: " + resp.status);
}
static String getHTTPVarString(Map<String, String> params) throws UnsupportedEncodingException {
String s = "";
for (Entry<String, String> e : params.entrySet()) {
String encodedValue = URLEncoder.encode(e.getValue(), "UTF-8");
s += "&" + e.getKey() + "=" + encodedValue;
}
s = s.substring(1);
return s;
}
public static String callProcOverJSONRaw(String varString, int expectedCode) throws Exception {
URL jsonAPIURL = new URL("http://localhost:8080/api/1.0/");
HttpURLConnection conn = (HttpURLConnection) jsonAPIURL.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.connect();
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(varString);
out.flush();
out.close();
out = null;
conn.getOutputStream().close();
BufferedReader in = null;
try {
if (conn.getInputStream() != null) {
in = new BufferedReader(
new InputStreamReader(
conn.getInputStream(), "UTF-8"));
}
} catch (IOException e) {
if (conn.getErrorStream() != null) {
in = new BufferedReader(
new InputStreamReader(
conn.getErrorStream(), "UTF-8"));
}
}
if (in == null) {
throw new Exception("Unable to read response from server");
}
StringBuffer decodedString = new StringBuffer();
String line;
while ((line = in.readLine()) != null) {
decodedString.append(line);
}
in.close();
in = null;
// get result code
int responseCode = conn.getResponseCode();
String response = decodedString.toString();
try {
conn.getInputStream().close();
conn.disconnect();
} // ignore closing problems here
catch (Exception e) {
}
conn = null;
//System.err.println(response);
return response;
}
public static String getHashedPasswordForHTTPVar(String password) {
assert (password != null);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte hashedPassword[] = null;
try {
hashedPassword = md.digest(password.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("JVM doesn't support UTF-8. Please use a supported JVM", e);
}
String retval = Encoder.hexEncode(hashedPassword);
return retval;
}
public static String callProcOverJSON(String procName, ParameterSet pset, String username, String password, boolean preHash) throws Exception {
return callProcOverJSON(procName, pset, username, password, preHash, false, 200 /* HTTP_OK */);
}
public static String callProcOverJSON(String procName, ParameterSet pset, String username, String password, boolean preHash, boolean admin) throws Exception {
return callProcOverJSON(procName, pset, username, password, preHash, admin, 200 /* HTTP_OK */);
}
public static String callProcOverJSON(String procName, ParameterSet pset, String username, String password, boolean preHash, boolean admin, int expectedCode) throws Exception {
// Call insert
String paramsInJSON = pset.toJSONString();
//System.out.println(paramsInJSON);
HashMap<String, String> params = new HashMap<String, String>();
params.put("Procedure", procName);
params.put("Parameters", paramsInJSON);
if (username != null) {
params.put("User", username);
}
if (password != null) {
if (preHash) {
params.put("Hashedpassword", getHashedPasswordForHTTPVar(password));
} else {
params.put("Password", password);
}
}
if (admin) {
params.put("admin", "true");
}
String varString = getHTTPVarString(params);
varString = getHTTPVarString(params);
return callProcOverJSONRaw(varString, expectedCode);
}
public static Response responseFromJSON(String jsonStr) throws JSONException, IOException {
Response response = new Response();
JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray resultsJson = jsonObj.getJSONArray("results");
response.results = new VoltTable[resultsJson.length()];
for (int i = 0; i < response.results.length; i++) {
JSONObject tableJson = resultsJson.getJSONObject(i);
response.results[i] = VoltTable.fromJSONObject(tableJson);
System.out.println(response.results[i].toString());
}
if (jsonObj.isNull("status") == false) {
response.status = (byte) jsonObj.getInt("status");
}
if (jsonObj.isNull("appstatus") == false) {
response.appStatus = (byte) jsonObj.getInt("appstatus");
}
if (jsonObj.isNull("statusstring") == false) {
response.statusString = jsonObj.getString("statusstring");
}
if (jsonObj.isNull("appstatusstring") == false) {
response.appStatusString = jsonObj.getString("appstatusstring");
}
if (jsonObj.isNull("exception") == false) {
response.exception = jsonObj.getString("exception");
}
return response;
}
public static Response callProcedure(String string, String key, byte[] storeValue) throws JSONException, IOException, Exception {
ParameterSet pset = ParameterSet.fromArrayNoCopy(key, storeValue);
System.out.println("Call proc: " + string + ". key: " + key + ". len(storeValue): " + storeValue.length);
String resp = callProcOverJSON(string, pset, username, password, prehash);
System.out.println("Response KV resp: " + resp.toString());
Response response = responseFromJSON(resp);
System.out.println("Response KV: " + response.toString());
return response;
}
public static Response callProcedure(String string, String generateRandomKeyForRetrieval) throws JSONException, IOException, Exception {
ParameterSet pset = ParameterSet.fromArrayNoCopy(generateRandomKeyForRetrieval);
System.out.println("Call proc: " + string + ". key: " + generateRandomKeyForRetrieval);
String resp = callProcOverJSON(string, pset, username, password, prehash);
System.out.println("Response K resp: " + resp.toString());
Response response = responseFromJSON(resp);
System.out.println("Response K: " + response.toString());
return response;
}
}