JSONUtils.java [src/csip/utils] Revision: Date:
/*
* $Id$
*
* This file is part of the Cloud Services Integration Platform (CSIP),
* a Model-as-a-Service framework, API and application suite.
*
* 2012-2022, Olaf David and others, OMSLab, Colorado State University.
*
* OMSLab licenses this file to you under the MIT license.
* See the LICENSE file in the project root for more information.
*/
package csip.utils;
import csip.Config;
import csip.ModelDataService;
import static csip.ModelDataService.KEY_PARAMETER;
import static csip.ModelDataService.KEY_RESULT;
import csip.api.server.ServiceException;
import java.io.File;
import java.util.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.SQLException;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import org.apache.commons.io.FileUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
*
* @author od
*/
public class JSONUtils {
public static int[] toIntArray(JSONArray arr) throws JSONException {
int[] a = new int[arr.length()];
for (int i = 0; i < a.length; i++) {
a[i] = arr.getInt(i);
}
return a;
}
public static boolean[] toBooleanArray(JSONArray arr) throws JSONException {
boolean[] a = new boolean[arr.length()];
for (int i = 0; i < a.length; i++) {
a[i] = arr.getBoolean(i);
}
return a;
}
public static long[] toLongArray(JSONArray arr) throws JSONException {
long[] a = new long[arr.length()];
for (int i = 0; i < a.length; i++) {
a[i] = arr.getLong(i);
}
return a;
}
public static double[] toDoubleArray(JSONArray arr) throws JSONException {
double[] a = new double[arr.length()];
for (int i = 0; i < a.length; i++) {
a[i] = arr.getDouble(i);
}
return a;
}
public static String[] toStringArray(JSONArray arr) throws JSONException {
String[] a = new String[arr.length()];
for (int i = 0; i < a.length; i++) {
a[i] = arr.getString(i);
}
return a;
}
public static String[][] to2DStringArray(JSONArray arr) throws JSONException {
String[][] a = new String[arr.length()][];
for (int i = 0; i < a.length; i++) {
JSONArray a2 = arr.getJSONArray(i);
a[i] = toStringArray(a2);
}
return a;
}
public static JSONArray toArray(Collection<?> val) {
return new JSONArray(val);
}
public static JSONArray toArray(double[] val) {
return new JSONArray(DoubleStream.of(val).boxed().collect(Collectors.toList()));
}
public static JSONArray toArray(boolean[] val) {
return new JSONArray(IntStream.range(0, val.length).mapToObj(idx -> val[idx]).collect(Collectors.toList()));
}
public static JSONArray toArray(long[] val) {
return new JSONArray(LongStream.range(0l, (long) val.length).mapToObj(idx -> val[(int) idx]).collect(Collectors.toList()));
}
public static JSONArray toArray(int[] val) {
return new JSONArray(IntStream.of(val).boxed().collect(Collectors.toList()));
}
public static JSONArray toArray(String[] val) {
return new JSONArray(Arrays.asList(val));
}
public static void mergeInto(JSONObject src, JSONObject dest) throws JSONException {
Iterator<?> i = src.keys();
while (i.hasNext()) {
String key = i.next().toString();
dest.put(key, src.get(key));
}
}
public static JSONObject clone(JSONObject o) throws JSONException {
return new JSONObject(o.toString());
}
public static String[] getNames(JSONObject o) {
Iterator<?> i = o.keys();
ArrayList<String> l = new ArrayList<>();
while (i.hasNext()) {
l.add(i.next().toString());
}
return l.toArray(new String[l.size()]);
}
public static boolean getBooleanParam(Map<String, JSONObject> param, String key, boolean def) {
try {
return (param.get(key) != null) ? param.get(key).getBoolean(ModelDataService.VALUE) : def;
} catch (JSONException ex) {
return def;
}
}
public static int getIntParam(Map<String, JSONObject> param, String key, int def) {
try {
return (param.get(key) != null) ? param.get(key).getInt(ModelDataService.VALUE) : def;
} catch (JSONException ex) {
return def;
}
}
public static double getDoubleParam(Map<String, JSONObject> param, String key, double def) {
try {
return (param.get(key) != null) ? param.get(key).getDouble(ModelDataService.VALUE) : def;
} catch (JSONException ex) {
return def;
}
}
public static long getJSONLong(JSONObject o, String key, long def) {
try {
return o.getLong(key);
} catch (JSONException ex) {
return def;
}
}
public static int getJSONInt(JSONObject o, String key, int def) {
try {
return o.getInt(key);
} catch (JSONException ex) {
return def;
}
}
public static String getJSONString(JSONObject o, String key, String def) {
try {
return o.getString(key);
} catch (JSONException ex) {
return def;
}
}
public static boolean getJSONBoolean(JSONObject o, String key, boolean def) {
try {
return o.getBoolean(key);
} catch (JSONException ex) {
return def;
}
}
public static Object getObjectParam(Map<String, JSONObject> param, String key, Object def) {
try {
return (param.get(key) != null) ? param.get(key).get(ModelDataService.VALUE) : def;
} catch (JSONException ex) {
return def;
}
}
public static String getStringParam(Map<String, JSONObject> param, String key, String def) {
try {
return (param.get(key) != null) ? param.get(key).getString(ModelDataService.VALUE) : def;
} catch (JSONException ex) {
return def;
}
}
public static JSONArray getJSONArrayParam(Map<String, JSONObject> param, String key) {
try {
return (param.get(key) != null) ? param.get(key).getJSONArray(ModelDataService.VALUE) : null;
} catch (JSONException ex) {
return null;
}
}
public static JSONObject getJSONObjectParam(Map<String, JSONObject> param, String key) {
try {
return (param.get(key) != null) ? param.get(key).getJSONObject(ModelDataService.VALUE) : null;
} catch (JSONException ex) {
return null;
}
}
public static JSONObject getJSONObjectGeometry(Map<String, JSONObject> param, String key) {
try {
return (param.get(key) != null) ? param.get(key).getJSONObject(ModelDataService.GEOMETRY) : null;
} catch (JSONException ex) {
return null;
}
}
public static void checkDouble(String msg, double val, double min, double max) {
if (Double.isNaN(val))
throw new IllegalArgumentException(msg + " no valid input " + val);
if (val < min || val > max)
throw new IllegalArgumentException(msg + " illegal value: " + val);
}
public static List<String> getRequestedResults(JSONObject metainfo) throws ServiceException {
List<String> l = new ArrayList<>();
try {
JSONArray j = metainfo.getJSONArray(ModelDataService.KEY_REQUEST_RESULTS);
for (int i = 0; i < j.length(); i++) {
l.add(j.getString(i));
}
} catch (JSONException ex) {
throw new ServiceException("No results requested.");
}
return l;
}
public static void checkValidResultRequest(JSONObject metainfo, Collection<String> results) throws ServiceException {
try {
JSONArray j = metainfo.getJSONArray(ModelDataService.KEY_REQUEST_RESULTS);
for (int i = 0; i < j.length(); i++) {
String name = j.getString(i);
if (!results.contains(name)) {
throw new ServiceException("unknown result request :" + name);
}
}
} catch (JSONException ex) {
throw new ServiceException("No results requested. Add one or more of : " + results.toString());
}
}
public static void checkKeyExists(Map<String, JSONObject> params, String key) throws ServiceException {
JSONObject j = params.get(key);
if (j == null)
throw new ServiceException("Key not found :" + key);
}
public static boolean checkKeyExistsB(Map<String, JSONObject> params, String key) {
JSONObject j = params.get(key);
return j != null;
}
public static boolean checkArrayExists(JSONObject obj, String arrayKey) {
try {
obj.getJSONArray(arrayKey);
return true;
} catch (JSONException e) {
return false;
}
}
public static void checkFileExists(JSONObject param, File dir) throws JSONException, ServiceException {
String file = param.getString(ModelDataService.VALUE);
if (file == null)
throw new ServiceException("Invalid File :" + param.getString(ModelDataService.VALUE));
if (!new File(dir, file).exists())
throw new ServiceException("File not found :" + param.getString(ModelDataService.VALUE));
}
public static Map<String, JSONObject> getParameter(JSONObject request) throws JSONException {
JSONArray param = request.getJSONArray(KEY_PARAMETER);
Map<String, JSONObject> pm = JSONUtils.preprocess(param);
return pm;
}
public static Map<String, JSONObject> getResults(JSONObject request) throws JSONException {
JSONArray param = request.getJSONArray(KEY_RESULT);
Map<String, JSONObject> pm = JSONUtils.preprocess(param);
return pm;
}
public static String getErrorStatus(JSONObject request) throws Exception {
JSONObject metainfo = request.getJSONObject(ModelDataService.KEY_METAINFO);
if (getStatus(request).equals(ModelDataService.FINISHED) && hasResult(request)) {
return null;
} else if (getStatus(request).equals(ModelDataService.SUBMITTED)) {
return null;
} else if (getStatus(request).equals(ModelDataService.RUNNING)) {
return null;
} else if (getStatus(request).equals(ModelDataService.FAILED) && metainfo.has("Error")) {
return metainfo.getString("Error");
}
return "Error";
}
public static int getPayloadVersion(Object params) {
if (params instanceof JSONArray)
return 1;
if (params instanceof JSONObject)
return 2;
throw new RuntimeException("Invalid payload structure");
}
public static Map<String, JSONObject> preprocess(Object params) throws JSONException {
Map<String, JSONObject> p = new HashMap<>();
switch (getPayloadVersion(params)) {
case 1: // payload version 1
JSONArray pa = (JSONArray) params;
for (int i = 0; i < pa.length(); i++) {
JSONObject o = pa.getJSONObject(i);
p.put(o.getString(ModelDataService.KEY_NAME), o);
}
break;
case 2: // payload version 2
JSONObject po = (JSONObject) params;
Iterator i = po.keys();
while (i.hasNext()) {
String key = i.next().toString();
p.put(key, po.getJSONObject(key));
}
}
return p;
}
public static JSONObject toV2(JSONArray results) throws JSONException {
JSONObject r = new JSONObject();
for (int i = 0; i < results.length(); i++) {
JSONObject o = results.getJSONObject(i);
r.put(o.getString(ModelDataService.KEY_NAME), o);
o.remove(ModelDataService.KEY_NAME);
}
return r;
}
static JSONArray toJsonArray(Map<String, JSONObject> params) throws JSONException {
JSONArray arr = new JSONArray();
SortedSet<String> keys = new TreeSet<>(params.keySet());
for (String key : keys) {
JSONObject value = params.get(key);
arr.put(value);
}
return arr;
}
public static JSONObject newRequest(JSONArray parameter, JSONObject metainfo) {
JSONObject req = new JSONObject();
try {
metainfo.put(ModelDataService.KEY_TSTAMP, Dates.nowISO());
req.put(ModelDataService.KEY_METAINFO, metainfo);
req.put(ModelDataService.KEY_PARAMETER, parameter);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return req;
}
public static void putRequestedMetaInfo(JSONObject req, JSONObject res, String key, Object val) throws JSONException {
if (req.getJSONObject(ModelDataService.KEY_METAINFO).has(key))
res.getJSONObject(ModelDataService.KEY_METAINFO).put(key, val);
}
public static void putRequestedMetaInfo(JSONObject metainfo, String key, Object val) throws JSONException {
if (metainfo.has(key))
metainfo.put(key, val);
}
public static JSONObject newResponse() {
JSONArray param = new JSONArray();
JSONArray result = new JSONArray();
JSONObject metainfo = new JSONObject();
return newResponse(param, result, metainfo);
}
public static JSONObject newRequest() {
JSONArray param = new JSONArray();
JSONObject metainfo = new JSONObject();
return newResponse(param, null, metainfo);
}
public static JSONObject newRequest(Map<String, JSONObject> params) throws JSONException {
JSONObject metainfo = new JSONObject();
return newResponse(toJsonArray(params), null, metainfo);
}
public static JSONObject newRequest(Map<String, JSONObject> params, JSONObject metainfo) throws JSONException {
return newResponse(toJsonArray(params), null, metainfo);
}
public static JSONObject newRequest(JSONObject metainfo) {
JSONArray param = new JSONArray();
return newResponse(param, null, metainfo);
}
public static JSONObject getMetaInfo(JSONObject object) throws ServiceException {
try {
return object.getJSONObject(ModelDataService.KEY_METAINFO);
} catch (JSONException ex) {
throw new ServiceException(ex);
}
}
public static JSONObject newResponse(JSONObject request, Object result, JSONObject metainfo) throws ServiceException {
try {
request.put(ModelDataService.KEY_METAINFO, metainfo);
if (result != null)
request.put(ModelDataService.KEY_RESULT, result);
} catch (JSONException ex) {
throw new ServiceException(ex);
}
return request;
}
public static JSONObject newResponse(JSONArray parameter, JSONArray result, JSONObject metainfo) {
JSONObject req = new JSONObject();
try {
req.put(ModelDataService.KEY_METAINFO, metainfo);
if (parameter != null)
req.put(ModelDataService.KEY_PARAMETER, parameter);
if (result != null)
req.put(ModelDataService.KEY_RESULT, result);
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
return req;
}
static final String GENERIC_SQL_EXCEPTION = "SQL failed with an exception, check logs for details.";
public static String getErrorMessage(Throwable E) {
// Controling the propagation of SQL messages such as failed sql queries
// via the return payload.
String message = E.getMessage();
if (message == null)
message = E.getClass().toString();
if (Config.getBoolean("csip.response.sqlfilter")) {
if (E instanceof SQLException)
return GENERIC_SQL_EXCEPTION;
// check if a SQLException is somewhere in the stacktrace.
Throwable cause = E.getCause();
while (cause != null) {
if (cause instanceof SQLException // only filter if SQLException message is in E
/*
* && (message.contains(cause.getMessage()))
*/)
return GENERIC_SQL_EXCEPTION;
cause = cause.getCause();
}
}
return message;
}
public static String getStringStackTrace(Throwable e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.close();
return sw.toString();
}
public static JSONArray getJSONStackTrace(Throwable e) {
String s = getStringStackTrace(e);
JSONArray arr = new JSONArray();
for (String st : s.split("\n")) {
arr.put(st.replace('\t', ' '));
}
return arr;
}
public static JSONObject newDeniedError(JSONObject meta, Object parameter, SecurityException err) {
JSONObject resp = new JSONObject();
try {
meta.put(ModelDataService.ERROR, getErrorMessage(err));
resp.put(ModelDataService.KEY_METAINFO, meta);
if (parameter != null)
resp.put(ModelDataService.KEY_PARAMETER, parameter);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return resp;
}
public static JSONObject newError(JSONObject meta, Object parameter, Throwable err) {
JSONObject resp = new JSONObject();
try {
meta.put(ModelDataService.ERROR, getErrorMessage(err));
if (Config.getBoolean("csip.response.stacktrace")) {
JSONArray trace = getJSONStackTrace(err);
if (trace != null)
meta.put("stacktrace", trace);
}
resp.put(ModelDataService.KEY_METAINFO, meta);
if (parameter != null)
resp.put(ModelDataService.KEY_PARAMETER, parameter);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return resp;
}
public static String toString(JSONObject o) {
int ind = Config.getInt(Config.CSIP_RESPONSE_JSONINDENT, 2);
if (ind < 1) {
return o.toString();
} else {
try {
return o.toString(ind);
} catch (JSONException ex) {
return o.toString();
}
}
}
public static JSONObject data(String name, Object value) throws JSONException {
return data(name, value, null);
}
public static JSONObject data(String name, JSONObject value) throws JSONException {
if (name == null)
throw new NullPointerException("name");
JSONObject param = new JSONObject();
param.put(ModelDataService.KEY_NAME, name);
param.put(ModelDataService.VALUE, value == null ? JSONObject.NULL : value);
return param;
}
public static JSONObject data(String name, Object value, String unit) throws JSONException {
if (name == null)
throw new NullPointerException("name");
JSONObject param = new JSONObject();
param.put(ModelDataService.KEY_NAME, name);
if (value == null) {
param.put(ModelDataService.VALUE, JSONObject.NULL);
} else if (value instanceof Collection) {
param.put(ModelDataService.VALUE, (Collection) value);
} else if (value instanceof Map) {
param.put(ModelDataService.VALUE, (Map) value);
} else {
param.put(ModelDataService.VALUE, value);
}
if (unit != null)
param.put(ModelDataService.KEY_UNIT, unit);
return param;
}
public static JSONObject dataDesc(String name, Object value, String desc) throws JSONException {
if (name == null)
throw new NullPointerException("name");
JSONObject param = new JSONObject();
param.put(ModelDataService.KEY_NAME, name);
param.put(ModelDataService.VALUE, value == null ? JSONObject.NULL : value);
if (desc != null)
param.put(ModelDataService.KEY_DESC, desc);
return param;
}
public static JSONObject data(String name, Object value, String descr, String unit) {
return dataUnitDesc(name, value, unit, descr);
}
public static JSONObject dataUnitDesc(String name, Object value, String unit, String desc) {
if (name == null)
throw new NullPointerException("name");
JSONObject param = new JSONObject();
try {
param.put(ModelDataService.KEY_NAME, name);
param.put(ModelDataService.VALUE, value == null ? JSONObject.NULL : value);
if (unit != null)
param.put(ModelDataService.KEY_UNIT, unit);
if (desc != null)
param.put(ModelDataService.KEY_DESC, desc);
return param;
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
}
public static JSONObject error(String text) {
JSONObject o = new JSONObject();
try {
o.put(ModelDataService.ERROR, text);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return o;
}
public static JSONObject ok(String text) {
JSONObject o = new JSONObject();
try {
o.put(ModelDataService.OK, text);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return o;
}
public static String getValue(JSONObject o) {
try {
return o.getString(ModelDataService.VALUE);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return null;
}
public static String getValueByKey(JSONArray a, String key) {
try {
for (int i = 0; i < a.length(); i++) {
JSONObject attr = a.getJSONObject(i);
if (attr.getString(ModelDataService.KEY_NAME).equals(key))
return attr.getString(ModelDataService.VALUE);
}
throw new JSONException("Key not found in array=" + key);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return null;
}
public static String getUnit(JSONObject o) {
try {
return o.getString(ModelDataService.UNIT);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return null;
}
public static boolean hasResult(JSONObject r) throws Exception {
if (r.has("result")) {
JSONArray response_result = r.getJSONArray("result");
return response_result.length() > 0;
}
return false;
}
public static String getSID(JSONObject r) throws JSONException {
JSONObject meta = r.getJSONObject("metainfo");
if (meta.has("suid"))
return meta.getString("suid");
return "";
}
public static boolean isAsync(JSONObject r) throws JSONException {
JSONObject meta = r.getJSONObject("metainfo");
if (meta.has("mode")) {
String mode = meta.getString("mode");
return mode.toLowerCase().equals("async");
}
return false;
}
public static String getStatus(JSONObject r) throws JSONException {
JSONObject meta = r.getJSONObject("metainfo");
if (meta.has("status"))
return meta.getString("status");
return "unknown";
}
public boolean hasRange(JSONObject o) {
return o.has(ModelDataService.RANGE);
}
public static double getRangeMin(JSONObject o) {
try {
return o.getJSONObject(ModelDataService.RANGE).getDouble(ModelDataService.MIN);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return Double.MIN_VALUE;
}
public static double getRangeMax(JSONObject o) throws JSONException {
try {
return o.getJSONObject(ModelDataService.RANGE).getDouble(ModelDataService.MAX);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return Double.MAX_VALUE;
}
public static String getDescription(JSONObject o) {
try {
return o.getString(ModelDataService.KEY_DESC);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return null;
}
public boolean hasIntent(JSONObject o) {
return o.has(ModelDataService.INTENT);
}
public static boolean isIn(JSONObject o) {
try {
return o.getString(ModelDataService.INTENT).toLowerCase().contains(ModelDataService.IN);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return false;
}
public static boolean isOut(JSONObject o) {
try {
return o.getString(ModelDataService.INTENT).toLowerCase().contains(ModelDataService.OUT);
} catch (JSONException ex) {
ex.printStackTrace(System.err);
}
return false;
}
public static boolean isInOut(JSONObject o) {
return isIn(o) && isOut(o);
}
public static JSONObject read(File file) throws Exception {
String f = FileUtils.readFileToString(file, "UTF-8");
JSONObject o = new JSONObject(f);
return o;
}
public static void write(JSONObject o, File file) throws Exception {
FileUtils.writeStringToFile(file, o.toString(2), "UTF-8");
}
}