diff --git a/core/src/main/java/org/opensearch/sql/datasource/model/DataSourceType.java b/core/src/main/java/org/opensearch/sql/datasource/model/DataSourceType.java index a3c7c73d6b..a557746d76 100644 --- a/core/src/main/java/org/opensearch/sql/datasource/model/DataSourceType.java +++ b/core/src/main/java/org/opensearch/sql/datasource/model/DataSourceType.java @@ -5,34 +5,53 @@ package org.opensearch.sql.datasource.model; -public enum DataSourceType { - PROMETHEUS("prometheus"), - OPENSEARCH("opensearch"), - SPARK("spark"), - S3GLUE("s3glue"); +import java.util.HashMap; +import java.util.Map; +import lombok.RequiredArgsConstructor; - private String text; +@RequiredArgsConstructor +public class DataSourceType { + public static DataSourceType PROMETHEUS = new DataSourceType("PROMETHEUS"); + public static DataSourceType OPENSEARCH = new DataSourceType("OPENSEARCH"); + public static DataSourceType SPARK = new DataSourceType("SPARK"); + public static DataSourceType S3GLUE = new DataSourceType("S3GLUE"); - DataSourceType(String text) { - this.text = text; + // Map from uppercase DataSourceType name to DataSourceType object + private static Map knownValues = new HashMap<>(); + + static { + register(PROMETHEUS, OPENSEARCH, SPARK, S3GLUE); + } + + private final String name; + + public String name() { + return name; } - public String getText() { - return this.text; + @Override + public String toString() { + return name; } - /** - * Get DataSourceType from text. - * - * @param text text. - * @return DataSourceType {@link DataSourceType}. - */ - public static DataSourceType fromString(String text) { - for (DataSourceType dataSourceType : DataSourceType.values()) { - if (dataSourceType.text.equalsIgnoreCase(text)) { - return dataSourceType; + /** Register DataSourceType to be used in fromString method */ + public static void register(DataSourceType ... dataSourceTypes) { + for (DataSourceType type : dataSourceTypes) { + String upperCaseName = type.name().toUpperCase(); + if (!knownValues.containsKey(upperCaseName)) { + knownValues.put(type.name().toUpperCase(), type); + } else { + throw new IllegalArgumentException("DataSourceType with name " + type.name() + " already exists"); } } - throw new IllegalArgumentException("No DataSourceType with text " + text + " found"); + } + + public static DataSourceType fromString(String name) { + String upperCaseName = name.toUpperCase(); + if (knownValues.containsKey(upperCaseName)) { + return knownValues.get(upperCaseName); + } else { + throw new IllegalArgumentException("No DataSourceType with name " + name + " found"); + } } } diff --git a/core/src/main/java/org/opensearch/sql/utils/SerializeUtils.java b/core/src/main/java/org/opensearch/sql/utils/SerializeUtils.java new file mode 100644 index 0000000000..3e30bdc563 --- /dev/null +++ b/core/src/main/java/org/opensearch/sql/utils/SerializeUtils.java @@ -0,0 +1,51 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import lombok.experimental.UtilityClass; +import org.opensearch.sql.datasource.model.DataSourceType; + +@UtilityClass +public class SerializeUtils { + private static class DataSourceTypeSerializer implements JsonSerializer { + @Override + public JsonElement serialize( + DataSourceType dataSourceType, + Type type, + JsonSerializationContext jsonSerializationContext) { + return new JsonPrimitive(dataSourceType.name()); + } + } + + private static class DataSourceTypeDeserializer implements JsonDeserializer { + @Override + public DataSourceType deserialize( + JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) + throws JsonParseException { + return DataSourceType.fromString(jsonElement.getAsString()); + } + } + + public static GsonBuilder getGsonBuilder() { + return new GsonBuilder() + .registerTypeAdapter(DataSourceType.class, new DataSourceTypeSerializer()) + .registerTypeAdapter(DataSourceType.class, new DataSourceTypeDeserializer()); + } + + public static Gson buildGson() { + return getGsonBuilder().create(); + } +} diff --git a/core/src/test/java/org/opensearch/sql/datasource/model/DataSourceTypeTest.java b/core/src/test/java/org/opensearch/sql/datasource/model/DataSourceTypeTest.java new file mode 100644 index 0000000000..de487be2e8 --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/datasource/model/DataSourceTypeTest.java @@ -0,0 +1,39 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.datasource.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +class DataSourceTypeTest { + @Test + public void fromString_succeed() { + testFromString("PROMETHEUS", DataSourceType.PROMETHEUS); + testFromString("OPENSEARCH", DataSourceType.OPENSEARCH); + testFromString("SPARK", DataSourceType.SPARK); + testFromString("S3GLUE", DataSourceType.S3GLUE); + + testFromString("prometheus", DataSourceType.PROMETHEUS); + } + + private void testFromString(String name, DataSourceType expectedType) { + assertEquals(expectedType, DataSourceType.fromString(name)); + } + + @Test + public void fromStringWithUnknownName_throws() { + assertThrows(IllegalArgumentException.class, () -> DataSourceType.fromString("UnknownName")); + } + + @Test + public void registerExistingType_throwsException() { + assertThrows( + IllegalArgumentException.class, + () -> DataSourceType.register(new DataSourceType("s3glue"))); + } +} diff --git a/core/src/test/java/org/opensearch/sql/utils/SerializeUtilsTest.java b/core/src/test/java/org/opensearch/sql/utils/SerializeUtilsTest.java new file mode 100644 index 0000000000..c3d387328e --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/utils/SerializeUtilsTest.java @@ -0,0 +1,65 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; +import org.junit.jupiter.api.Test; +import org.opensearch.sql.datasource.model.DataSourceMetadata; +import org.opensearch.sql.datasource.model.DataSourceStatus; +import org.opensearch.sql.datasource.model.DataSourceType; + +class SerializeUtilsTest { + @Test + public void buildGson_serializeDataSourceTypeAsString() { + DataSourceMetadata dataSourceMetadata = + new DataSourceMetadata.Builder() + .setName("DATASOURCE_NAME") + .setDescription("DESCRIPTION") + .setConnector(DataSourceType.S3GLUE) + .setAllowedRoles(ImmutableList.of("ROLE")) + .setResultIndex("query_execution_result_test") + .setDataSourceStatus(DataSourceStatus.ACTIVE) + .build(); + + Gson gson = SerializeUtils.buildGson(); + String json = gson.toJson(dataSourceMetadata); + + // connector should be serialized as string (not as object) + assertJsonAttribute(json, "connector", "S3GLUE"); + // other attribute should be serialized as normal + assertJsonAttribute(json, "name", "DATASOURCE_NAME"); + assertJsonAttribute(json, "description", "DESCRIPTION"); + assertJsonAttribute(json, "resultIndex", "query_execution_result_test"); + assertJsonAttribute(json, "status", "ACTIVE"); + assertTrue(json.contains("\"allowedRoles\":[\"ROLE\"]")); + } + + private void assertJsonAttribute(String json, String attribute, String value) { + assertTrue(json.contains("\"" + attribute + "\":\"" + value + "\"")); + } + + @Test + public void buildGson_deserializeDataSourceTypeFromString() { + String json = + "{\"name\":\"DATASOURCE_NAME\"," + + "\"description\":\"DESCRIPTION\"," + + "\"connector\":\"S3GLUE\"," + + "\"allowedRoles\":[\"ROLE\"]," + + "\"properties\":{}," + + "\"resultIndex\":\"query_execution_result_test\"," + + "\"status\":\"ACTIVE\"" + + "}"; + + Gson gson = SerializeUtils.buildGson(); + DataSourceMetadata metadata = gson.fromJson(json, DataSourceMetadata.class); + + assertEquals(DataSourceType.S3GLUE, metadata.getConnector()); + } +} diff --git a/datasources/src/main/java/org/opensearch/sql/datasources/exceptions/ErrorMessage.java b/datasources/src/main/java/org/opensearch/sql/datasources/exceptions/ErrorMessage.java index 4a57b76b1d..a0c0f5e24d 100644 --- a/datasources/src/main/java/org/opensearch/sql/datasources/exceptions/ErrorMessage.java +++ b/datasources/src/main/java/org/opensearch/sql/datasources/exceptions/ErrorMessage.java @@ -6,10 +6,10 @@ package org.opensearch.sql.datasources.exceptions; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import lombok.Getter; import org.opensearch.core.rest.RestStatus; +import org.opensearch.sql.utils.SerializeUtils; /** Error Message. */ public class ErrorMessage { @@ -61,7 +61,7 @@ public String toString() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("status", status); jsonObject.add("error", getErrorAsJson()); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); + Gson gson = SerializeUtils.getGsonBuilder().setPrettyPrinting().create(); return gson.toJson(jsonObject); } diff --git a/datasources/src/test/java/org/opensearch/sql/datasources/exceptions/ErrorMessageTest.java b/datasources/src/test/java/org/opensearch/sql/datasources/exceptions/ErrorMessageTest.java index d7a9d73d61..eb4d575f8c 100644 --- a/datasources/src/test/java/org/opensearch/sql/datasources/exceptions/ErrorMessageTest.java +++ b/datasources/src/test/java/org/opensearch/sql/datasources/exceptions/ErrorMessageTest.java @@ -13,9 +13,33 @@ class ErrorMessageTest { @Test - void fetchReason() { + void toString_returnPrettyPrintedJson() { ErrorMessage errorMessage = new ErrorMessage(new RuntimeException(), RestStatus.TOO_MANY_REQUESTS.getStatus()); - assertEquals("Too Many Requests", errorMessage.getReason()); + + assertEquals( + "{\n" + + " \"status\": 429,\n" + + " \"error\": {\n" + + " \"type\": \"RuntimeException\",\n" + + " \"reason\": \"Too Many Requests\",\n" + + " \"details\": \"\"\n" + + " }\n" + + "}", + errorMessage.toString()); + } + + @Test + void getReason() { + testGetReason(RestStatus.TOO_MANY_REQUESTS, "Too Many Requests"); + testGetReason(RestStatus.BAD_REQUEST, "Invalid Request"); + // other status + testGetReason(RestStatus.BAD_GATEWAY, "There was internal problem at backend"); + } + + void testGetReason(RestStatus status, String expectedReason) { + ErrorMessage errorMessage = new ErrorMessage(new RuntimeException(), status.getStatus()); + + assertEquals(expectedReason, errorMessage.getReason()); } } diff --git a/datasources/src/test/java/org/opensearch/sql/datasources/storage/OpenSearchDataSourceMetadataStorageTest.java b/datasources/src/test/java/org/opensearch/sql/datasources/storage/OpenSearchDataSourceMetadataStorageTest.java index 886e84298d..55b7528f60 100644 --- a/datasources/src/test/java/org/opensearch/sql/datasources/storage/OpenSearchDataSourceMetadataStorageTest.java +++ b/datasources/src/test/java/org/opensearch/sql/datasources/storage/OpenSearchDataSourceMetadataStorageTest.java @@ -8,8 +8,13 @@ import static org.opensearch.sql.datasource.model.DataSourceStatus.ACTIVE; import static org.opensearch.sql.datasources.storage.OpenSearchDataSourceMetadataStorage.DATASOURCE_INDEX_NAME; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -645,8 +650,7 @@ private String getBasicDataSourceMetadataString() throws JsonProcessingException .setConnector(DataSourceType.PROMETHEUS) .setAllowedRoles(Collections.singletonList("prometheus_access")) .build(); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.writeValueAsString(dataSourceMetadata); + return serialize(dataSourceMetadata); } private String getOldDataSourceMetadataStringWithOutStatusEnum() { @@ -666,8 +670,7 @@ private String getAWSSigv4DataSourceMetadataString() throws JsonProcessingExcept .setConnector(DataSourceType.PROMETHEUS) .setAllowedRoles(Collections.singletonList("prometheus_access")) .build(); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.writeValueAsString(dataSourceMetadata); + return serialize(dataSourceMetadata); } private String getDataSourceMetadataStringWithBasicAuthentication() @@ -684,8 +687,7 @@ private String getDataSourceMetadataStringWithBasicAuthentication() .setConnector(DataSourceType.PROMETHEUS) .setAllowedRoles(Collections.singletonList("prometheus_access")) .build(); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.writeValueAsString(dataSourceMetadata); + return serialize(dataSourceMetadata); } private String getDataSourceMetadataStringWithNoAuthentication() throws JsonProcessingException { @@ -698,8 +700,7 @@ private String getDataSourceMetadataStringWithNoAuthentication() throws JsonProc .setConnector(DataSourceType.PROMETHEUS) .setAllowedRoles(Collections.singletonList("prometheus_access")) .build(); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.writeValueAsString(dataSourceMetadata); + return serialize(dataSourceMetadata); } private DataSourceMetadata getDataSourceMetadata() { @@ -715,4 +716,32 @@ private DataSourceMetadata getDataSourceMetadata() { .setAllowedRoles(Collections.singletonList("prometheus_access")) .build(); } + + private String serialize(DataSourceMetadata dataSourceMetadata) throws JsonProcessingException { + return getObjectMapper().writeValueAsString(dataSourceMetadata); + } + + private ObjectMapper getObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + addSerializerForDataSourceType(mapper); + return mapper; + } + + /** It is needed to serialize DataSourceType as string. */ + private void addSerializerForDataSourceType(ObjectMapper mapper) { + SimpleModule module = new SimpleModule(); + module.addSerializer(DataSourceType.class, getDataSourceTypeSerializer()); + mapper.registerModule(module); + } + + private StdSerializer getDataSourceTypeSerializer() { + return new StdSerializer<>(DataSourceType.class) { + @Override + public void serialize( + DataSourceType dsType, JsonGenerator jsonGen, SerializerProvider provider) + throws IOException { + jsonGen.writeString(dsType.name()); + } + }; + } } diff --git a/datasources/src/test/java/org/opensearch/sql/datasources/transport/TransportGetDataSourceActionTest.java b/datasources/src/test/java/org/opensearch/sql/datasources/transport/TransportGetDataSourceActionTest.java index 90bd7bb025..22118a676e 100644 --- a/datasources/src/test/java/org/opensearch/sql/datasources/transport/TransportGetDataSourceActionTest.java +++ b/datasources/src/test/java/org/opensearch/sql/datasources/transport/TransportGetDataSourceActionTest.java @@ -7,7 +7,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.Collections; @@ -34,6 +33,7 @@ import org.opensearch.sql.legacy.metrics.Metrics; import org.opensearch.sql.opensearch.setting.OpenSearchSettings; import org.opensearch.sql.protocol.response.format.JsonResponseFormatter; +import org.opensearch.sql.utils.SerializeUtils; import org.opensearch.tasks.Task; import org.opensearch.transport.TransportService; @@ -77,6 +77,7 @@ public void testDoExecute() { when(dataSourceService.getDataSourceMetadata("test_datasource")).thenReturn(dataSourceMetadata); action.doExecute(task, request, actionListener); + verify(dataSourceService, times(1)).getDataSourceMetadata("test_datasource"); Mockito.verify(actionListener).onResponse(getDataSourceActionResponseArgumentCaptor.capture()); GetDataSourceActionResponse getDataSourceActionResponse = @@ -92,7 +93,8 @@ protected Object buildJsonObject(DataSourceMetadata response) { dataSourceMetadataJsonResponseFormatter.format(dataSourceMetadata), getDataSourceActionResponse.getResult()); DataSourceMetadata result = - new Gson().fromJson(getDataSourceActionResponse.getResult(), DataSourceMetadata.class); + SerializeUtils.buildGson() + .fromJson(getDataSourceActionResponse.getResult(), DataSourceMetadata.class); Assertions.assertEquals("test_datasource", result.getName()); Assertions.assertEquals(DataSourceType.PROMETHEUS, result.getConnector()); } @@ -109,6 +111,7 @@ public void testDoExecuteForGetAllDataSources() { .thenReturn(Collections.singleton(dataSourceMetadata)); action.doExecute(task, request, actionListener); + verify(dataSourceService, times(1)).getDataSourceMetadata(false); Mockito.verify(actionListener).onResponse(getDataSourceActionResponseArgumentCaptor.capture()); GetDataSourceActionResponse getDataSourceActionResponse = @@ -125,7 +128,7 @@ protected Object buildJsonObject(Set response) { dataSourceMetadataJsonResponseFormatter.format(Collections.singleton(dataSourceMetadata)), getDataSourceActionResponse.getResult()); Set result = - new Gson().fromJson(getDataSourceActionResponse.getResult(), setType); + SerializeUtils.buildGson().fromJson(getDataSourceActionResponse.getResult(), setType); DataSourceMetadata resultDataSource = result.iterator().next(); Assertions.assertEquals("test_datasource", resultDataSource.getName()); Assertions.assertEquals(DataSourceType.PROMETHEUS, resultDataSource.getConnector()); @@ -135,7 +138,9 @@ protected Object buildJsonObject(Set response) { public void testDoExecuteWithException() { doThrow(new RuntimeException("Error")).when(dataSourceService).getDataSourceMetadata("testDS"); GetDataSourceActionRequest request = new GetDataSourceActionRequest("testDS"); + action.doExecute(task, request, actionListener); + verify(dataSourceService, times(1)).getDataSourceMetadata("testDS"); Mockito.verify(actionListener).onFailure(exceptionArgumentCaptor.capture()); Exception exception = exceptionArgumentCaptor.getValue(); diff --git a/datasources/src/test/java/org/opensearch/sql/datasources/utils/XContentParserUtilsTest.java b/datasources/src/test/java/org/opensearch/sql/datasources/utils/XContentParserUtilsTest.java index c6f08b673b..c1b1cfc70c 100644 --- a/datasources/src/test/java/org/opensearch/sql/datasources/utils/XContentParserUtilsTest.java +++ b/datasources/src/test/java/org/opensearch/sql/datasources/utils/XContentParserUtilsTest.java @@ -17,6 +17,7 @@ import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.sql.datasource.model.DataSourceMetadata; import org.opensearch.sql.datasource.model.DataSourceType; +import org.opensearch.sql.utils.SerializeUtils; @ExtendWith(MockitoExtension.class) public class XContentParserUtilsTest { @@ -50,7 +51,7 @@ public void testToDataSourceMetadataFromJson() { .setProperties(Map.of("prometheus.uri", "https://localhost:9090")) .setResultIndex("query_execution_result2") .build(); - Gson gson = new Gson(); + Gson gson = SerializeUtils.buildGson(); String json = gson.toJson(dataSourceMetadata); DataSourceMetadata retrievedMetadata = XContentParserUtils.toDataSourceMetadata(json); @@ -94,8 +95,7 @@ public void testToMapFromJson() { STATUS_FIELD, ACTIVE); - Gson gson = new Gson(); - String json = gson.toJson(dataSourceData); + String json = SerializeUtils.buildGson().toJson(dataSourceData); Map parsedData = XContentParserUtils.toMap(json); @@ -122,8 +122,7 @@ public void testToDataSourceMetadataFromJsonWithoutNameAndConnector() { @Test public void testToMapFromJsonWithoutName() { Map dataSourceData = new HashMap<>(Map.of(DESCRIPTION_FIELD, "test")); - Gson gson = new Gson(); - String json = gson.toJson(dataSourceData); + String json = SerializeUtils.buildGson().toJson(dataSourceData); IllegalArgumentException exception = assertThrows( @@ -139,8 +138,7 @@ public void testToMapFromJsonWithoutName() { public void testToDataSourceMetadataFromJsonUsingUnknownObject() { HashMap hashMap = new HashMap<>(); hashMap.put("test", "test"); - Gson gson = new Gson(); - String json = gson.toJson(hashMap); + String json = SerializeUtils.buildGson().toJson(hashMap); IllegalArgumentException exception = assertThrows( @@ -156,8 +154,7 @@ public void testToDataSourceMetadataFromJsonUsingUnknownObject() { public void testToMapFromJsonUsingUnknownObject() { HashMap hashMap = new HashMap<>(); hashMap.put("test", "test"); - Gson gson = new Gson(); - String json = gson.toJson(hashMap); + String json = SerializeUtils.buildGson().toJson(hashMap); IllegalArgumentException exception = assertThrows( diff --git a/integ-test/src/test/java/org/opensearch/sql/datasource/DataSourceAPIsIT.java b/integ-test/src/test/java/org/opensearch/sql/datasource/DataSourceAPIsIT.java index 05e19f8285..5d693d6652 100644 --- a/integ-test/src/test/java/org/opensearch/sql/datasource/DataSourceAPIsIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/datasource/DataSourceAPIsIT.java @@ -14,7 +14,6 @@ import static org.opensearch.sql.legacy.TestUtils.getResponseBody; import com.google.common.collect.ImmutableMap; -import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; import java.io.IOException; @@ -34,6 +33,7 @@ import org.opensearch.sql.datasource.model.DataSourceMetadata; import org.opensearch.sql.datasource.model.DataSourceType; import org.opensearch.sql.ppl.PPLIntegTestCase; +import org.opensearch.sql.utils.SerializeUtils; public class DataSourceAPIsIT extends PPLIntegTestCase { @@ -103,7 +103,7 @@ public void createDataSourceAPITest() { Assert.assertEquals(200, getResponse.getStatusLine().getStatusCode()); String getResponseString = getResponseBody(getResponse); DataSourceMetadata dataSourceMetadata = - new Gson().fromJson(getResponseString, DataSourceMetadata.class); + SerializeUtils.buildGson().fromJson(getResponseString, DataSourceMetadata.class); Assert.assertEquals( "https://localhost:9090", dataSourceMetadata.getProperties().get("prometheus.uri")); Assert.assertEquals( @@ -152,7 +152,7 @@ public void updateDataSourceAPITest() { Assert.assertEquals(200, getResponse.getStatusLine().getStatusCode()); String getResponseString = getResponseBody(getResponse); DataSourceMetadata dataSourceMetadata = - new Gson().fromJson(getResponseString, DataSourceMetadata.class); + SerializeUtils.buildGson().fromJson(getResponseString, DataSourceMetadata.class); Assert.assertEquals( "https://randomtest.com:9090", dataSourceMetadata.getProperties().get("prometheus.uri")); Assert.assertEquals("", dataSourceMetadata.getDescription()); @@ -176,7 +176,7 @@ public void updateDataSourceAPITest() { Assert.assertEquals(200, getResponseAfterPatch.getStatusLine().getStatusCode()); String getResponseStringAfterPatch = getResponseBody(getResponseAfterPatch); DataSourceMetadata dataSourceMetadataAfterPatch = - new Gson().fromJson(getResponseStringAfterPatch, DataSourceMetadata.class); + SerializeUtils.buildGson().fromJson(getResponseStringAfterPatch, DataSourceMetadata.class); Assert.assertEquals( "https://randomtest.com:9090", dataSourceMetadataAfterPatch.getProperties().get("prometheus.uri")); @@ -216,7 +216,8 @@ public void deleteDataSourceTest() { 404, prometheusGetResponseException.getResponse().getStatusLine().getStatusCode()); String prometheusGetResponseString = getResponseBody(prometheusGetResponseException.getResponse()); - JsonObject errorMessage = new Gson().fromJson(prometheusGetResponseString, JsonObject.class); + JsonObject errorMessage = + SerializeUtils.buildGson().fromJson(prometheusGetResponseString, JsonObject.class); Assert.assertEquals( "DataSource with name delete_prometheus doesn't exist.", errorMessage.get("error").getAsJsonObject().get("details").getAsString()); @@ -243,7 +244,7 @@ public void getAllDataSourceTest() { String getResponseString = getResponseBody(getResponse); Type listType = new TypeToken>() {}.getType(); List dataSourceMetadataList = - new Gson().fromJson(getResponseString, listType); + SerializeUtils.buildGson().fromJson(getResponseString, listType); Assert.assertTrue( dataSourceMetadataList.stream().anyMatch(ds -> ds.getName().equals("get_all_prometheus"))); } @@ -283,7 +284,7 @@ public void issue2196() { Assert.assertEquals(200, getResponse.getStatusLine().getStatusCode()); String getResponseString = getResponseBody(getResponse); DataSourceMetadata dataSourceMetadata = - new Gson().fromJson(getResponseString, DataSourceMetadata.class); + SerializeUtils.buildGson().fromJson(getResponseString, DataSourceMetadata.class); Assert.assertEquals( "https://localhost:9090", dataSourceMetadata.getProperties().get("prometheus.uri")); Assert.assertEquals( @@ -310,7 +311,8 @@ public void datasourceLimitTest() throws InterruptedException, IOException { ResponseException.class, () -> client().performRequest(getCreateDataSourceRequest(d2))); Assert.assertEquals(400, exception.getResponse().getStatusLine().getStatusCode()); String prometheusGetResponseString = getResponseBody(exception.getResponse()); - JsonObject errorMessage = new Gson().fromJson(prometheusGetResponseString, JsonObject.class); + JsonObject errorMessage = + SerializeUtils.buildGson().fromJson(prometheusGetResponseString, JsonObject.class); Assert.assertEquals( "domain concurrent datasources can not exceed 1", errorMessage.get("error").getAsJsonObject().get("details").getAsString()); @@ -373,7 +375,7 @@ public void patchDataSourceAPITest() { Assert.assertEquals(200, getResponse.getStatusLine().getStatusCode()); String getResponseString = getResponseBody(getResponse); DataSourceMetadata dataSourceMetadata = - new Gson().fromJson(getResponseString, DataSourceMetadata.class); + SerializeUtils.buildGson().fromJson(getResponseString, DataSourceMetadata.class); Assert.assertEquals( "https://localhost:9090", dataSourceMetadata.getProperties().get("prometheus.uri")); Assert.assertEquals( diff --git a/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java b/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java index 058182f123..8a0ad563a6 100644 --- a/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java +++ b/integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java @@ -40,7 +40,6 @@ import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT; import com.google.common.base.Strings; -import com.google.gson.Gson; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; @@ -67,6 +66,7 @@ import org.opensearch.client.RestClient; import org.opensearch.sql.common.setting.Settings; import org.opensearch.sql.datasource.model.DataSourceMetadata; +import org.opensearch.sql.utils.SerializeUtils; /** OpenSearch Rest integration test base for SQL testing */ public abstract class SQLIntegTestCase extends OpenSearchSQLRestTestCase { @@ -473,7 +473,7 @@ protected JSONObject getSource(JSONObject hit) { protected static Request getCreateDataSourceRequest(DataSourceMetadata dataSourceMetadata) { Request request = new Request("POST", "/_plugins/_query/_datasources"); - request.setJsonEntity(new Gson().toJson(dataSourceMetadata)); + request.setJsonEntity(SerializeUtils.buildGson().toJson(dataSourceMetadata)); RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); restOptionsBuilder.addHeader("Content-Type", "application/json"); request.setOptions(restOptionsBuilder); @@ -482,7 +482,7 @@ protected static Request getCreateDataSourceRequest(DataSourceMetadata dataSourc protected static Request getUpdateDataSourceRequest(DataSourceMetadata dataSourceMetadata) { Request request = new Request("PUT", "/_plugins/_query/_datasources"); - request.setJsonEntity(new Gson().toJson(dataSourceMetadata)); + request.setJsonEntity(SerializeUtils.buildGson().toJson(dataSourceMetadata)); RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); restOptionsBuilder.addHeader("Content-Type", "application/json"); request.setOptions(restOptionsBuilder); @@ -491,7 +491,7 @@ protected static Request getUpdateDataSourceRequest(DataSourceMetadata dataSourc protected static Request getPatchDataSourceRequest(Map dataSourceData) { Request request = new Request("PATCH", "/_plugins/_query/_datasources"); - request.setJsonEntity(new Gson().toJson(dataSourceData)); + request.setJsonEntity(SerializeUtils.buildGson().toJson(dataSourceData)); RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); restOptionsBuilder.addHeader("Content-Type", "application/json"); request.setOptions(restOptionsBuilder); diff --git a/protocol/src/main/java/org/opensearch/sql/protocol/response/format/ErrorFormatter.java b/protocol/src/main/java/org/opensearch/sql/protocol/response/format/ErrorFormatter.java index 5c85e5d65b..2e43cfa6c2 100644 --- a/protocol/src/main/java/org/opensearch/sql/protocol/response/format/ErrorFormatter.java +++ b/protocol/src/main/java/org/opensearch/sql/protocol/response/format/ErrorFormatter.java @@ -6,12 +6,12 @@ package org.opensearch.sql.protocol.response.format; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import java.security.AccessController; import java.security.PrivilegedAction; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.experimental.UtilityClass; +import org.opensearch.sql.utils.SerializeUtils; @UtilityClass public class ErrorFormatter { @@ -19,10 +19,15 @@ public class ErrorFormatter { private static final Gson PRETTY_PRINT_GSON = AccessController.doPrivileged( (PrivilegedAction) - () -> new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create()); + () -> + SerializeUtils.getGsonBuilder() + .setPrettyPrinting() + .disableHtmlEscaping() + .create()); private static final Gson GSON = AccessController.doPrivileged( - (PrivilegedAction) () -> new GsonBuilder().disableHtmlEscaping().create()); + (PrivilegedAction) + () -> SerializeUtils.getGsonBuilder().disableHtmlEscaping().create()); /** Util method to format {@link Throwable} response to JSON string in compact printing. */ public static String compactFormat(Throwable t) { diff --git a/spark/src/main/java/org/opensearch/sql/spark/asyncquery/model/AsyncQueryJobMetadata.java b/spark/src/main/java/org/opensearch/sql/spark/asyncquery/model/AsyncQueryJobMetadata.java index 1ffb780ef1..1cfab4832d 100644 --- a/spark/src/main/java/org/opensearch/sql/spark/asyncquery/model/AsyncQueryJobMetadata.java +++ b/spark/src/main/java/org/opensearch/sql/spark/asyncquery/model/AsyncQueryJobMetadata.java @@ -6,13 +6,13 @@ package org.opensearch.sql.spark.asyncquery.model; import com.google.common.collect.ImmutableMap; -import com.google.gson.Gson; import lombok.Builder.Default; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.SuperBuilder; import org.opensearch.sql.spark.dispatcher.model.JobType; import org.opensearch.sql.spark.execution.statestore.StateModel; +import org.opensearch.sql.utils.SerializeUtils; /** This class models all the metadata required for a job. */ @Data @@ -38,7 +38,7 @@ public class AsyncQueryJobMetadata extends StateModel { @Override public String toString() { - return new Gson().toJson(this); + return SerializeUtils.buildGson().toJson(this); } /** copy builder. update seqNo and primaryTerm */ diff --git a/spark/src/main/java/org/opensearch/sql/spark/config/SparkExecutionEngineConfigClusterSetting.java b/spark/src/main/java/org/opensearch/sql/spark/config/SparkExecutionEngineConfigClusterSetting.java index 338107f8a3..0347f5ffc1 100644 --- a/spark/src/main/java/org/opensearch/sql/spark/config/SparkExecutionEngineConfigClusterSetting.java +++ b/spark/src/main/java/org/opensearch/sql/spark/config/SparkExecutionEngineConfigClusterSetting.java @@ -6,8 +6,8 @@ package org.opensearch.sql.spark.config; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.google.gson.Gson; import lombok.Data; +import org.opensearch.sql.utils.SerializeUtils; /** * This POJO is just for reading stringified json in `plugins.query.executionengine.spark.config` @@ -27,6 +27,7 @@ public class SparkExecutionEngineConfigClusterSetting { public static SparkExecutionEngineConfigClusterSetting toSparkExecutionEngineConfig( String jsonString) { - return new Gson().fromJson(jsonString, SparkExecutionEngineConfigClusterSetting.class); + return SerializeUtils.buildGson() + .fromJson(jsonString, SparkExecutionEngineConfigClusterSetting.class); } }