Skip to content

Commit

Permalink
Merge pull request IQSS#10062 from bencomp/10054-10056-json-reader
Browse files Browse the repository at this point in the history
All the tests related to this change passed and I talked about my questions/concerns about this change with the Dev team.
  • Loading branch information
jp-tosca authored Nov 13, 2023
2 parents d3fbee5 + 235c038 commit e284402
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 64 deletions.
22 changes: 10 additions & 12 deletions src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.util.SystemConfig;
import edu.harvard.iq.dataverse.util.json.JsonParser;
import edu.harvard.iq.dataverse.util.json.JsonUtil;
import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder;
import edu.harvard.iq.dataverse.validation.PasswordValidatorServiceBean;
import java.io.StringReader;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -62,9 +62,9 @@
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;
import jakarta.json.JsonValue.ValueType;
import jakarta.persistence.EntityManager;
Expand Down Expand Up @@ -132,23 +132,21 @@ public Response refineResponse( String message ) {
* In the common case of the wrapped response being of type JSON,
* return the message field it has (if any).
* @return the content of a message field, or {@code null}.
* @throws JsonException when JSON parsing fails.
*/
String getWrappedMessageWhenJson() {
if ( response.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE) ) {
Object entity = response.getEntity();
if ( entity == null ) return null;

String json = entity.toString();
try ( StringReader rdr = new StringReader(json) ){
JsonReader jrdr = Json.createReader(rdr);
JsonObject obj = jrdr.readObject();
if ( obj.containsKey("message") ) {
JsonValue message = obj.get("message");
return message.getValueType() == ValueType.STRING ? obj.getString("message") : message.toString();
} else {
return null;
}
JsonObject obj = JsonUtil.getJsonObject(entity.toString());
if ( obj.containsKey("message") ) {
JsonValue message = obj.get("message");
return message.getValueType() == ValueType.STRING ? obj.getString("message") : message.toString();
} else {
return null;
}

} else {
return null;
}
Expand Down
46 changes: 21 additions & 25 deletions src/main/java/edu/harvard/iq/dataverse/api/MakeDataCountApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import edu.harvard.iq.dataverse.makedatacount.DatasetMetricsServiceBean;
import edu.harvard.iq.dataverse.settings.JvmSettings;
import edu.harvard.iq.dataverse.util.SystemConfig;
import edu.harvard.iq.dataverse.util.json.JsonUtil;

import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -83,26 +83,21 @@ public Response sendDataToHub() {
@Path("{id}/addUsageMetricsFromSushiReport")
public Response addUsageMetricsFromSushiReport(@PathParam("id") String id, @QueryParam("reportOnDisk") String reportOnDisk) {

JsonObject report;

try (FileReader reader = new FileReader(reportOnDisk)) {
report = Json.createReader(reader).readObject();
Dataset dataset;
try {
dataset = findDatasetOrDie(id);
List<DatasetMetrics> datasetMetrics = datasetMetricsService.parseSushiReport(report, dataset);
if (!datasetMetrics.isEmpty()) {
for (DatasetMetrics dm : datasetMetrics) {
datasetMetricsService.save(dm);
}
try {
JsonObject report = JsonUtil.getJsonObjectFromFile(reportOnDisk);
Dataset dataset = findDatasetOrDie(id);
List<DatasetMetrics> datasetMetrics = datasetMetricsService.parseSushiReport(report, dataset);
if (!datasetMetrics.isEmpty()) {
for (DatasetMetrics dm : datasetMetrics) {
datasetMetricsService.save(dm);
}
} catch (WrappedResponse ex) {
Logger.getLogger(MakeDataCountApi.class.getName()).log(Level.SEVERE, null, ex);
return error(Status.BAD_REQUEST, "Wrapped response: " + ex.getLocalizedMessage());
}
} catch (WrappedResponse ex) {
logger.log(Level.SEVERE, null, ex);
return error(Status.BAD_REQUEST, "Wrapped response: " + ex.getLocalizedMessage());

} catch (IOException ex) {
System.out.print(ex.getMessage());
logger.log(Level.WARNING, ex.getMessage());
return error(Status.BAD_REQUEST, "IOException: " + ex.getLocalizedMessage());
}
String msg = "Dummy Data has been added to dataset " + id;
Expand All @@ -113,10 +108,8 @@ public Response addUsageMetricsFromSushiReport(@PathParam("id") String id, @Quer
@Path("/addUsageMetricsFromSushiReport")
public Response addUsageMetricsFromSushiReportAll(@PathParam("id") String id, @QueryParam("reportOnDisk") String reportOnDisk) {

JsonObject report;

try (FileReader reader = new FileReader(reportOnDisk)) {
report = Json.createReader(reader).readObject();
try {
JsonObject report = JsonUtil.getJsonObjectFromFile(reportOnDisk);

List<DatasetMetrics> datasetMetrics = datasetMetricsService.parseSushiReport(report, null);
if (!datasetMetrics.isEmpty()) {
Expand All @@ -126,7 +119,7 @@ public Response addUsageMetricsFromSushiReportAll(@PathParam("id") String id, @Q
}

} catch (IOException ex) {
System.out.print(ex.getMessage());
logger.log(Level.WARNING, ex.getMessage());
return error(Status.BAD_REQUEST, "IOException: " + ex.getLocalizedMessage());
}
String msg = "Usage Metrics Data has been added to all datasets from file " + reportOnDisk;
Expand All @@ -135,7 +128,7 @@ public Response addUsageMetricsFromSushiReportAll(@PathParam("id") String id, @Q

@POST
@Path("{id}/updateCitationsForDataset")
public Response updateCitationsForDataset(@PathParam("id") String id) throws MalformedURLException, IOException {
public Response updateCitationsForDataset(@PathParam("id") String id) throws IOException {
try {
Dataset dataset = findDatasetOrDie(id);
String persistentId = dataset.getGlobalId().toString();
Expand All @@ -158,7 +151,10 @@ public Response updateCitationsForDataset(@PathParam("id") String id) throws Mal
logger.warning("Failed to get citations from " + url.toString());
return error(Status.fromStatusCode(status), "Failed to get citations from " + url.toString());
}
JsonObject report = Json.createReader(connection.getInputStream()).readObject();
JsonObject report;
try (InputStream inStream = connection.getInputStream()) {
report = JsonUtil.getJsonObject(inStream);
}
JsonObject links = report.getJsonObject("links");
JsonArray data = report.getJsonArray("data");
Iterator<JsonValue> iter = data.iterator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
import edu.harvard.iq.dataverse.util.json.JsonUtil;

import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;

@RequiredPermissions(Permission.EditDataset)
public class GetProvJsonCommand extends AbstractCommand<JsonObject> {
Expand All @@ -35,13 +35,13 @@ public JsonObject execute(CommandContext ctxt) throws CommandException {

try {
StorageIO<DataFile> dataAccess = dataFile.getStorageIO();
InputStream inputStream = dataAccess.getAuxFileAsInputStream(provJsonExtension);
JsonObject jsonObject = null;
if(null != inputStream) {
JsonReader jsonReader = Json.createReader(inputStream);
jsonObject = jsonReader.readObject();
try (InputStream inputStream = dataAccess.getAuxFileAsInputStream(provJsonExtension)) {
JsonObject jsonObject = null;
if (null != inputStream) {
jsonObject = JsonUtil.getJsonObject(inputStream);
}
return jsonObject;
}
return jsonObject;
} catch (IOException ex) {
String error = "Exception caught in DataAccess.getStorageIO(dataFile) getting file. Error: " + ex;
throw new IllegalCommandException(error, this);
Expand Down
85 changes: 71 additions & 14 deletions src/main/java/edu/harvard/iq/dataverse/util/json/JsonUtil.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package edu.harvard.iq.dataverse.util.json;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
import jakarta.json.JsonWriter;
import jakarta.json.JsonWriterFactory;
Expand All @@ -20,17 +22,19 @@ public class JsonUtil {

private static final Logger logger = Logger.getLogger(JsonUtil.class.getCanonicalName());

private JsonUtil() {}

/**
* Make an attempt at pretty printing a String but will return the original
* string if it isn't JSON or if there is any exception.
*/
public static String prettyPrint(String jsonString) {
try {
com.google.gson.JsonParser jsonParser = new com.google.gson.JsonParser();
JsonObject jsonObject = jsonParser.parse(jsonString).getAsJsonObject();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = gson.toJson(jsonObject);
return prettyJson;
if (jsonString.trim().startsWith("{")) {
return prettyPrint(getJsonObject(jsonString));
} else {
return prettyPrint(getJsonArray(jsonString));
}
} catch (Exception ex) {
logger.info("Returning original string due to exception: " + ex);
return jsonString;
Expand All @@ -48,7 +52,7 @@ public static String prettyPrint(JsonArray jsonArray) {
return stringWriter.toString();
}

public static String prettyPrint(jakarta.json.JsonObject jsonObject) {
public static String prettyPrint(JsonObject jsonObject) {
Map<String, Boolean> config = new HashMap<>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
JsonWriterFactory jsonWriterFactory = Json.createWriterFactory(config);
Expand All @@ -58,16 +62,69 @@ public static String prettyPrint(jakarta.json.JsonObject jsonObject) {
}
return stringWriter.toString();
}

public static jakarta.json.JsonObject getJsonObject(String serializedJson) {

/**
* Return the contents of the string as a JSON object.
* This method closes its resources when an exception occurs, but does
* not catch any exceptions.
* @param serializedJson the JSON object serialized as a {@code String}
* @throws JsonException when parsing fails.
* @see #getJsonObject(InputStream)
* @see #getJsonObjectFromFile(String)
* @see #getJsonArray(String)
*/
public static JsonObject getJsonObject(String serializedJson) {
try (StringReader rdr = new StringReader(serializedJson)) {
try (JsonReader jsonReader = Json.createReader(rdr)) {
return jsonReader.readObject();
}
}
}

public static jakarta.json.JsonArray getJsonArray(String serializedJson) {

/**
* Return the contents of the {@link InputStream} as a JSON object.
*
* This method closes its resources when an exception occurs, but does
* not catch any exceptions.
* The caller of this method is responsible for closing the provided stream.
* @param stream the input stream to read from
* @throws JsonException when parsing fails.
* @see #getJsonObject(String)
* @see #getJsonObjectFromFile(String)
*/
public static JsonObject getJsonObject(InputStream stream) {
try (JsonReader jsonReader = Json.createReader(stream)) {
return jsonReader.readObject();
}
}

/**
* Return the contents of the file as a JSON object.
* This method closes its resources when an exception occurs, but does
* not catch any exceptions.
* @param fileName the name of the file to read from
* @throws FileNotFoundException when the file cannot be opened for reading
* @throws JsonException when parsing fails.
* @see #getJsonObject(String)
* @see #getJsonObject(InputStream)
*/
public static JsonObject getJsonObjectFromFile(String fileName) throws IOException {
try (FileReader rdr = new FileReader(fileName)) {
try (JsonReader jsonReader = Json.createReader(rdr)) {
return jsonReader.readObject();
}
}
}

/**
* Return the contents of the string as a JSON array.
* This method closes its resources when an exception occurs, but does
* not catch any exceptions.
* @param serializedJson the JSON array serialized as a {@code String}
* @throws JsonException when parsing fails.
* @see #getJsonObject(String)
*/
public static JsonArray getJsonArray(String serializedJson) {
try (StringReader rdr = new StringReader(serializedJson)) {
try (JsonReader jsonReader = Json.createReader(rdr)) {
return jsonReader.readArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

public class JsonUtilTest {
class JsonUtilTest {

@Test
public void testPrettyPrint() {
JsonUtil jsonUtil = new JsonUtil();
void testPrettyPrint() {
String nullString = null;
assertEquals(null, JsonUtil.prettyPrint(nullString));
assertEquals("", JsonUtil.prettyPrint(""));
assertEquals("junk", JsonUtil.prettyPrint("junk"));
assertEquals("{}", JsonUtil.prettyPrint("{}"));
assertEquals("{\n" + " \"foo\": \"bar\"\n" + "}", JsonUtil.prettyPrint("{\"foo\": \"bar\"}"));
assertEquals("{\n}", JsonUtil.prettyPrint("{}"));
assertEquals("[\n \"junk\"\n]", JsonUtil.prettyPrint("[\"junk\"]"));
assertEquals("{\n" + " \"foo\": \"bar\"\n" + "}", JsonUtil.prettyPrint("{\"foo\": \"bar\"}"));
}

}

0 comments on commit e284402

Please sign in to comment.