This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 3c8f936e4cd HDDS-15808. Replace json-simple with Jackson in
httpfsgateway (#10710)
3c8f936e4cd is described below
commit 3c8f936e4cdaa124cf2134acd8e30cf3b78a0022
Author: Siyao Meng <[email protected]>
AuthorDate: Fri Jul 10 11:13:47 2026 -0700
HDDS-15808. Replace json-simple with Jackson in httpfsgateway (#10710)
Co-authored-by: Claude Opus 4.8 <[email protected]>
---
hadoop-ozone/dist/src/main/license/bin/LICENSE.txt | 1 -
hadoop-ozone/dist/src/main/license/jar-report.txt | 1 -
hadoop-ozone/httpfsgateway/pom.xml | 16 ++--
.../apache/ozone/fs/http/server/FSOperations.java | 106 ++++++++++-----------
.../apache/ozone/fs/http/server/HttpFSServer.java | 13 ++-
.../instrumentation/InstrumentationService.java | 64 +++----------
.../org/apache/ozone/lib/wsrs/JSONMapProvider.java | 9 +-
.../org/apache/ozone/lib/wsrs/JSONProvider.java | 79 ---------------
.../TestInstrumentationSerialization.java | 78 +++++++++++++++
.../apache/ozone/lib/wsrs/TestJSONMapProvider.java | 71 ++++++++++++++
pom.xml | 6 --
11 files changed, 232 insertions(+), 212 deletions(-)
diff --git a/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
b/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
index 0c509fa5964..8456581dfc2 100644
--- a/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
+++ b/hadoop-ozone/dist/src/main/license/bin/LICENSE.txt
@@ -298,7 +298,6 @@ Apache License 2.0
com.google.inject.extensions:guice-servlet
com.google.inject:guice
com.google.j2objc:j2objc-annotations
- com.googlecode.json-simple:json-simple
com.jolbox:bonecp
com.lmax:disruptor
com.nimbusds:nimbus-jose-jwt
diff --git a/hadoop-ozone/dist/src/main/license/jar-report.txt
b/hadoop-ozone/dist/src/main/license/jar-report.txt
index 274f5385721..1ab2063cf5c 100644
--- a/hadoop-ozone/dist/src/main/license/jar-report.txt
+++ b/hadoop-ozone/dist/src/main/license/jar-report.txt
@@ -165,7 +165,6 @@ share/ozone/lib/jooq-codegen.jar
share/ozone/lib/jooq-meta.jar
share/ozone/lib/jooq.jar
share/ozone/lib/jsch.jar
-share/ozone/lib/json-simple.jar
share/ozone/lib/jsp-api.jar
share/ozone/lib/jspecify.jar
share/ozone/lib/jsr311-api.jar
diff --git a/hadoop-ozone/httpfsgateway/pom.xml
b/hadoop-ozone/httpfsgateway/pom.xml
index 4da62ff003f..a8562e52c14 100644
--- a/hadoop-ozone/httpfsgateway/pom.xml
+++ b/hadoop-ozone/httpfsgateway/pom.xml
@@ -44,17 +44,15 @@
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
</dependency>
<dependency>
- <groupId>com.googlecode.json-simple</groupId>
- <artifactId>json-simple</artifactId>
- <exclusions>
- <exclusion>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </exclusion>
- </exclusions>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
diff --git
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/FSOperations.java
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/FSOperations.java
index 55d90ef9901..eb2998e9cf6 100644
---
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/FSOperations.java
+++
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/FSOperations.java
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.LinkedHashMap;
@@ -60,8 +61,6 @@
import org.apache.ozone.fs.http.HttpFSConstants;
import org.apache.ozone.fs.http.HttpFSConstants.FILETYPE;
import org.apache.ozone.lib.service.FileSystemAccess;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
/**
* FileSystem operation executors used by {@link HttpFSServer}.
@@ -107,7 +106,7 @@ private static Map<String, Object> toJson(FileStatus[]
fileStatuses,
boolean isFile) {
Map<String, Object> json = new LinkedHashMap<>();
Map<String, Object> inner = new LinkedHashMap<>();
- JSONArray statuses = new JSONArray();
+ List<Map<String, Object>> statuses = new ArrayList<>();
for (FileStatus f : fileStatuses) {
statuses.add(toJsonInner(f, isFile));
}
@@ -209,7 +208,7 @@ private static Map<String, Object>
toJson(FileSystem.DirectoryEntries
private static Map<String, Object> aclStatusToJSON(AclStatus aclStatus) {
Map<String, Object> json = new LinkedHashMap<String, Object>();
Map<String, Object> inner = new LinkedHashMap<String, Object>();
- JSONArray entriesArray = new JSONArray();
+ List<String> entriesArray = new ArrayList<>();
inner.put(HttpFSConstants.OWNER_JSON, aclStatus.getOwner());
inner.put(HttpFSConstants.GROUP_JSON, aclStatus.getGroup());
inner.put(HttpFSConstants.PERMISSION_JSON,
@@ -254,14 +253,13 @@ private static Map fileChecksumToJSON(FileChecksum
checksum) {
* @return The JSON representation of the xAttrs.
* @throws IOException
*/
- @SuppressWarnings({"unchecked", "rawtypes"})
- private static Map xAttrsToJSON(Map<String, byte[]> xAttrs,
+ private static Map<String, Object> xAttrsToJSON(Map<String, byte[]> xAttrs,
XAttrCodec encoding) throws IOException {
- Map jsonMap = new LinkedHashMap();
- JSONArray jsonArray = new JSONArray();
+ Map<String, Object> jsonMap = new LinkedHashMap<>();
+ List<Map<String, Object>> jsonArray = new ArrayList<>();
if (xAttrs != null) {
for (Entry<String, byte[]> e : xAttrs.entrySet()) {
- Map json = new LinkedHashMap();
+ Map<String, Object> json = new LinkedHashMap<>();
json.put(HttpFSConstants.XATTR_NAME_JSON, e.getKey());
if (e.getValue() != null) {
json.put(HttpFSConstants.XATTR_VALUE_JSON,
@@ -286,7 +284,7 @@ private static Map xAttrsToJSON(Map<String, byte[]> xAttrs,
private static Map xAttrNamesToJSON(List<String> names) throws IOException {
Map jsonMap = new LinkedHashMap();
jsonMap.put(HttpFSConstants.XATTRNAMES_JSON,
- JSONArray.toJSONString(names));
+ JsonUtil.toJsonString(names));
return jsonMap;
}
@@ -364,27 +362,26 @@ private static Map<String, Object>
quotaUsageToMap(QuotaUsage quotaUsage) {
}
/**
- * Converts an object into a Json Map with with one key-value entry.
+ * Converts an object into a Json Map with one key-value entry.
* <p/>
- * It assumes the given value is either a JSON primitive type or a
- * <code>JsonAware</code> instance.
+ * The value may be a JSON primitive, a Map or List, or any object that
+ * Jackson can serialize.
*
* @param name name for the key of the entry.
* @param value for the value of the entry.
*
* @return the JSON representation of the key-value pair.
*/
- @SuppressWarnings("unchecked")
- private static JSONObject toJSON(String name, Object value) {
- JSONObject json = new JSONObject();
+ private static Map<String, Object> toJSON(String name, Object value) {
+ Map<String, Object> json = new LinkedHashMap<>();
json.put(name, value);
return json;
}
- @SuppressWarnings({ "unchecked" })
- private static JSONObject storagePolicyToJSON(BlockStoragePolicySpi policy) {
+ private static Map<String, Object> storagePolicyToJSON(
+ BlockStoragePolicySpi policy) {
BlockStoragePolicy p = (BlockStoragePolicy) policy;
- JSONObject policyJson = new JSONObject();
+ Map<String, Object> policyJson = new LinkedHashMap<>();
policyJson.put("id", p.getId());
policyJson.put("name", p.getName());
policyJson.put("storageTypes", toJsonArray(p.getStorageTypes()));
@@ -395,24 +392,22 @@ private static JSONObject
storagePolicyToJSON(BlockStoragePolicySpi policy) {
return policyJson;
}
- @SuppressWarnings("unchecked")
- private static JSONArray toJsonArray(StorageType[] storageTypes) {
- JSONArray jsonArray = new JSONArray();
+ private static List<String> toJsonArray(StorageType[] storageTypes) {
+ List<String> jsonArray = new ArrayList<>();
for (StorageType type : storageTypes) {
jsonArray.add(type.toString());
}
return jsonArray;
}
- @SuppressWarnings("unchecked")
- private static JSONObject storagePoliciesToJSON(
+ private static Map<String, Object> storagePoliciesToJSON(
Collection<? extends BlockStoragePolicySpi> storagePolicies) {
- JSONObject json = new JSONObject();
- JSONArray jsonArray = new JSONArray();
- JSONObject policies = new JSONObject();
+ Map<String, Object> json = new LinkedHashMap<>();
+ List<Map<String, Object>> jsonArray = new ArrayList<>();
+ Map<String, Object> policies = new LinkedHashMap<>();
if (storagePolicies != null) {
for (BlockStoragePolicySpi policy : storagePolicies) {
- JSONObject policyMap = storagePolicyToJSON(policy);
+ Map<String, Object> policyMap = storagePolicyToJSON(policy);
jsonArray.add(policyMap);
}
}
@@ -507,8 +502,8 @@ public Void execute(FileSystem fs) throws IOException {
* Executor that performs a truncate FileSystemAccess files system operation.
*/
@InterfaceAudience.Private
- public static class FSTruncate implements
- FileSystemAccess.FileSystemExecutor<JSONObject> {
+ public static class FSTruncate implements
+ FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
private long newLength;
@@ -537,7 +532,7 @@ public FSTruncate(String path, long newLength) {
* @throws IOException thrown if an IO error occurred.
*/
@Override
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
boolean result = fs.truncate(path, newLength);
HttpFSServerWebApp.get().getMetrics().incrOpsTruncate();
return toJSON(
@@ -730,7 +725,7 @@ public static long copyBytes(InputStream in, OutputStream
out, long count)
*/
@InterfaceAudience.Private
public static class FSDelete
- implements FileSystemAccess.FileSystemExecutor<JSONObject> {
+ implements FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
private boolean recursive;
@@ -756,7 +751,7 @@ public FSDelete(String path, boolean recursive) {
* @throws IOException thrown if an IO error occurred.
*/
@Override
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
boolean deleted = fs.delete(path, recursive);
HttpFSServerWebApp.get().getMetrics().incrOpsDelete();
return toJSON(
@@ -842,7 +837,7 @@ public Map execute(FileSystem fs) throws IOException {
*/
@InterfaceAudience.Private
public static class FSHomeDir
- implements FileSystemAccess.FileSystemExecutor<JSONObject> {
+ implements FileSystemAccess.FileSystemExecutor<Map> {
/**
* Executes the filesystem operation.
@@ -854,10 +849,9 @@ public static class FSHomeDir
* @throws IOException thrown if an IO error occurred.
*/
@Override
- @SuppressWarnings("unchecked")
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
Path homeDir = fs.getHomeDirectory();
- JSONObject json = new JSONObject();
+ Map<String, Object> json = new LinkedHashMap<>();
json.put(HttpFSConstants.HOME_DIR_JSON, homeDir.toUri().getPath());
return json;
}
@@ -955,7 +949,7 @@ public Map execute(FileSystem fs) throws IOException {
*/
@InterfaceAudience.Private
public static class FSMkdirs
- implements FileSystemAccess.FileSystemExecutor<JSONObject> {
+ implements FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
private short permission;
@@ -986,7 +980,7 @@ public FSMkdirs(String path, short permission,
* @throws IOException thrown if an IO error occurred.
*/
@Override
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
FsPermission fsPermission = new FsPermission(permission);
if (unmaskedPermission != -1) {
fsPermission = FsCreateModes.create(fsPermission,
@@ -1039,7 +1033,7 @@ public InputStream execute(FileSystem fs) throws
IOException {
*/
@InterfaceAudience.Private
public static class FSRename
- implements FileSystemAccess.FileSystemExecutor<JSONObject> {
+ implements FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
private Path toPath;
@@ -1065,7 +1059,7 @@ public FSRename(String path, String toPath) {
* @throws IOException thrown if an IO error occurred.
*/
@Override
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
boolean renamed = fs.rename(path, toPath);
HttpFSServerWebApp.get().getMetrics().incrOpsRename();
return toJSON(HttpFSConstants.RENAME_JSON, renamed);
@@ -1343,7 +1337,7 @@ public Void execute(FileSystem fs) throws IOException {
*/
@InterfaceAudience.Private
public static class FSTrashRoot
- implements FileSystemAccess.FileSystemExecutor<JSONObject> {
+ implements FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
public FSTrashRoot(String path) {
@@ -1351,10 +1345,9 @@ public FSTrashRoot(String path) {
}
@Override
- @SuppressWarnings("unchecked")
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
Path trashRoot = fs.getTrashRoot(this.path);
- JSONObject json = new JSONObject();
+ Map<String, Object> json = new LinkedHashMap<>();
json.put(HttpFSConstants.TRASH_DIR_JSON, trashRoot.toUri().getPath());
return json;
}
@@ -1401,7 +1394,7 @@ public Map execute(FileSystem fs) throws IOException {
*/
@InterfaceAudience.Private
public static class FSSetReplication
- implements FileSystemAccess.FileSystemExecutor<JSONObject> {
+ implements FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
private short replication;
@@ -1427,10 +1420,9 @@ public FSSetReplication(String path, short replication) {
* @throws IOException thrown if an IO error occurred.
*/
@Override
- @SuppressWarnings("unchecked")
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
boolean ret = fs.setReplication(path, replication);
- JSONObject json = new JSONObject();
+ Map<String, Object> json = new LinkedHashMap<>();
json.put(HttpFSConstants.SET_REPLICATION_JSON, ret);
return json;
}
@@ -1610,13 +1602,12 @@ public Map execute(FileSystem fs) throws IOException {
* Executor that performs a getAllStoragePolicies FileSystemAccess files
* system operation.
*/
- @SuppressWarnings({ "unchecked" })
@InterfaceAudience.Private
public static class FSGetAllStoragePolicies implements
- FileSystemAccess.FileSystemExecutor<JSONObject> {
+ FileSystemAccess.FileSystemExecutor<Map> {
@Override
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
Collection<? extends BlockStoragePolicySpi> storagePolicies = fs
.getAllStoragePolicies();
return storagePoliciesToJSON(storagePolicies);
@@ -1627,10 +1618,9 @@ public JSONObject execute(FileSystem fs) throws
IOException {
* Executor that performs a getStoragePolicy FileSystemAccess files system
* operation.
*/
- @SuppressWarnings({ "unchecked" })
@InterfaceAudience.Private
public static class FSGetStoragePolicy implements
- FileSystemAccess.FileSystemExecutor<JSONObject> {
+ FileSystemAccess.FileSystemExecutor<Map> {
private Path path;
@@ -1639,9 +1629,9 @@ public FSGetStoragePolicy(String path) {
}
@Override
- public JSONObject execute(FileSystem fs) throws IOException {
+ public Map execute(FileSystem fs) throws IOException {
BlockStoragePolicySpi storagePolicy = fs.getStoragePolicy(path);
- JSONObject json = new JSONObject();
+ Map<String, Object> json = new LinkedHashMap<>();
json.put(HttpFSConstants.STORAGE_POLICY_JSON,
storagePolicyToJSON(storagePolicy));
return json;
@@ -1793,9 +1783,9 @@ public FSCreateSnapshot(String path, String snapshotName)
{
@Override
public String execute(FileSystem fs) throws IOException {
Path snapshotPath = fs.createSnapshot(path, snapshotName);
- JSONObject json = toJSON(HttpFSConstants.HOME_DIR_JSON,
+ Map<String, Object> json = toJSON(HttpFSConstants.HOME_DIR_JSON,
snapshotPath.toString());
- return json.toJSONString().replaceAll("\\\\", "");
+ return JsonUtil.toJsonString(json);
}
}
diff --git
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/HttpFSServer.java
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/HttpFSServer.java
index 262b9fa6945..c6ac62a7f3f 100644
---
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/HttpFSServer.java
+++
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/fs/http/server/HttpFSServer.java
@@ -83,7 +83,6 @@
import org.apache.ozone.lib.servlet.FileSystemReleaseFilter;
import org.apache.ozone.lib.wsrs.InputStreamEntity;
import org.apache.ozone.lib.wsrs.Parameters;
-import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
@@ -402,7 +401,7 @@ private Response handleGetStoragePolicy(String path,
Response response;
FSOperations.FSGetStoragePolicy command =
new FSOperations.FSGetStoragePolicy(path);
- JSONObject json = fsExecute(user, command);
+ Map json = fsExecute(user, command);
AUDIT_LOG.info("[{}]", path);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
return response;
@@ -414,7 +413,7 @@ private Response handleGetAllStoragePolicy(String path,
Response response;
FSOperations.FSGetAllStoragePolicies command =
new FSOperations.FSGetAllStoragePolicies();
- JSONObject json = fsExecute(user, command);
+ Map json = fsExecute(user, command);
AUDIT_LOG.info("[{}]", path);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
return response;
@@ -649,7 +648,7 @@ private Response handleDelete(String path,
AUDIT_LOG.info("[{}] recursive [{}]", path, recursive);
FSOperations.FSDelete command
= new FSOperations.FSDelete(path, recursive);
- JSONObject json = fsExecute(user, command);
+ Map json = fsExecute(user, command);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
return response;
}
@@ -769,7 +768,7 @@ private Response handleTruncate(String path,
Long newLength = params.get(NewLengthParam.NAME, NewLengthParam.class);
FSOperations.FSTruncate command
= new FSOperations.FSTruncate(path, newLength);
- JSONObject json = fsExecute(user, command);
+ Map json = fsExecute(user, command);
AUDIT_LOG.info("Truncate [{}] to length [{}]", path, newLength);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
return response;
@@ -1078,7 +1077,7 @@ private Response handleRename(String path,
String toPath = params.get(DestinationParam.NAME, DestinationParam.class);
FSOperations.FSRename command
= new FSOperations.FSRename(path, toPath);
- JSONObject json = fsExecute(user, command);
+ Map json = fsExecute(user, command);
AUDIT_LOG.info("[{}] to [{}]", path, toPath);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
return response;
@@ -1095,7 +1094,7 @@ private Response handleMkdirs(String path,
UnmaskedPermissionParam.class);
FSOperations.FSMkdirs command =
new FSOperations.FSMkdirs(path, permission, unmaskedPermission);
- JSONObject json = fsExecute(user, command);
+ Map json = fsExecute(user, command);
AUDIT_LOG.info("[{}] permission [{}] unmaskedpermission [{}]",
path, permission, unmaskedPermission);
response = Response.ok(json).type(MediaType.APPLICATION_JSON).build();
diff --git
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/service/instrumentation/InstrumentationService.java
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/service/instrumentation/InstrumentationService.java
index 28b87518f34..d441df55efd 100644
---
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/service/instrumentation/InstrumentationService.java
+++
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/service/instrumentation/InstrumentationService.java
@@ -17,8 +17,7 @@
package org.apache.ozone.lib.service.instrumentation;
-import java.io.IOException;
-import java.io.Writer;
+import com.fasterxml.jackson.annotation.JsonValue;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -34,9 +33,6 @@
import org.apache.ozone.lib.server.ServiceException;
import org.apache.ozone.lib.service.Instrumentation;
import org.apache.ozone.lib.service.Scheduler;
-import org.json.simple.JSONAware;
-import org.json.simple.JSONObject;
-import org.json.simple.JSONStreamAware;
/**
* Hadoop server instrumentation.
@@ -195,7 +191,7 @@ void end() {
}
- static class Timer implements JSONAware, JSONStreamAware {
+ static class Timer {
static final int LAST_TOTAL = 0;
static final int LAST_OWN = 1;
static final int AVG_TOTAL = 2;
@@ -251,10 +247,10 @@ void addCron(Cron cron) {
}
}
- @SuppressWarnings("unchecked")
- private JSONObject getJSON() {
+ @JsonValue
+ Map<String, Object> getJSON() {
long[] values = getValues();
- JSONObject json = new JSONObject();
+ Map<String, Object> json = new LinkedHashMap<>();
json.put("lastTotal", values[0]);
json.put("lastOwn", values[1]);
json.put("avgTotal", values[2]);
@@ -262,16 +258,6 @@ private JSONObject getJSON() {
return json;
}
- @Override
- public String toJSONString() {
- return getJSON().toJSONString();
- }
-
- @Override
- public void writeJSONString(Writer out) throws IOException {
- getJSON().writeJSONString(out);
- }
-
}
@Override
@@ -295,9 +281,9 @@ public void addCron(String group, String name,
Instrumentation.Cron cron) {
timer.addCron((Cron) cron);
}
- static class VariableHolder<E> implements JSONAware, JSONStreamAware {
- // Supressed, because it is only used in this class or in test files,
- // but the tests will be removed later.
+ static class VariableHolder<E> {
+ // Package-private and mutable so the enclosing service can assign it
+ // directly; suppress the visibility check.
@SuppressWarnings("checkstyle:VisibilityModifier")
Variable<E> var;
@@ -308,23 +294,13 @@ static class VariableHolder<E> implements JSONAware,
JSONStreamAware {
this.var = var;
}
- @SuppressWarnings("unchecked")
- private JSONObject getJSON() {
- JSONObject json = new JSONObject();
+ @JsonValue
+ Map<String, Object> getJSON() {
+ Map<String, Object> json = new LinkedHashMap<>();
json.put("value", var.getValue());
return json;
}
- @Override
- public String toJSONString() {
- return getJSON().toJSONString();
- }
-
- @Override
- public void writeJSONString(Writer out) throws IOException {
- out.write(toJSONString());
- }
-
}
@Override
@@ -334,7 +310,7 @@ public void addVariable(String group, String name,
Variable<?> variable) {
holder.var = variable;
}
- static class Sampler implements JSONAware, JSONStreamAware {
+ static class Sampler {
private Variable<Long> variable;
private long[] values;
private AtomicLong sum;
@@ -362,23 +338,13 @@ void sample() {
((full) ? values.length : ((last == 0) ? 1 : last));
}
- @SuppressWarnings("unchecked")
- private JSONObject getJSON() {
- JSONObject json = new JSONObject();
+ @JsonValue
+ Map<String, Object> getJSON() {
+ Map<String, Object> json = new LinkedHashMap<>();
json.put("sampler", getRate());
json.put("size", (full) ? values.length : last);
return json;
}
-
- @Override
- public String toJSONString() {
- return getJSON().toJSONString();
- }
-
- @Override
- public void writeJSONString(Writer out) throws IOException {
- out.write(toJSONString());
- }
}
@Override
diff --git
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONMapProvider.java
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONMapProvider.java
index bdb75490f83..232993effe6 100644
---
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONMapProvider.java
+++
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONMapProvider.java
@@ -17,6 +17,8 @@
package org.apache.ozone.lib.wsrs;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -33,7 +35,6 @@
import javax.ws.rs.ext.Provider;
import org.apache.hadoop.hdds.annotation.InterfaceAudience;
import org.apache.hadoop.http.JettyUtils;
-import org.json.simple.JSONObject;
/**
* A <code>MessageBodyWriter</code> implementation providing a JSON map.
@@ -43,6 +44,10 @@
@InterfaceAudience.Private
public class JSONMapProvider implements MessageBodyWriter<Map> {
private static final String ENTER = System.getProperty("line.separator");
+ // AUTO_CLOSE_TARGET is disabled so the underlying response stream stays
+ // open for the trailing newline and container-managed close.
+ private static final ObjectMapper MAPPER = new ObjectMapper()
+ .disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
@Override
public boolean isWriteable(Class<?> aClass,
@@ -72,7 +77,7 @@ public void writeTo(Map map,
throws IOException, WebApplicationException {
Writer writer
= new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
- JSONObject.writeJSONString(map, writer);
+ MAPPER.writeValue(writer, map);
writer.write(ENTER);
writer.flush();
}
diff --git
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONProvider.java
b/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONProvider.java
deleted file mode 100644
index b98d4db19f1..00000000000
---
a/hadoop-ozone/httpfsgateway/src/main/java/org/apache/ozone/lib/wsrs/JSONProvider.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ozone.lib.wsrs;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.nio.charset.StandardCharsets;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-import org.apache.hadoop.hdds.annotation.InterfaceAudience;
-import org.apache.hadoop.http.JettyUtils;
-import org.json.simple.JSONStreamAware;
-
-/**
- * A <code>MessageBodyWriter</code> implementation providing a JSON stream.
- */
-@Provider
-@Produces(MediaType.APPLICATION_JSON + "; " + JettyUtils.UTF_8)
[email protected]
-public class JSONProvider implements MessageBodyWriter<JSONStreamAware> {
- private static final String ENTER = System.getProperty("line.separator");
-
- @Override
- public boolean isWriteable(Class<?> aClass,
- Type type,
- Annotation[] annotations,
- MediaType mediaType) {
- return JSONStreamAware.class.isAssignableFrom(aClass);
- }
-
- @Override
- public long getSize(JSONStreamAware jsonStreamAware,
- Class<?> aClass,
- Type type,
- Annotation[] annotations,
- MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(JSONStreamAware jsonStreamAware,
- Class<?> aClass,
- Type type,
- Annotation[] annotations,
- MediaType mediaType,
- MultivaluedMap<String, Object>
stringObjectMultivaluedMap,
- OutputStream outputStream)
- throws IOException, WebApplicationException {
- Writer writer
- = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
- jsonStreamAware.writeJSONString(writer);
- writer.write(ENTER);
- writer.flush();
- }
-
-}
diff --git
a/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/service/instrumentation/TestInstrumentationSerialization.java
b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/service/instrumentation/TestInstrumentationSerialization.java
new file mode 100644
index 00000000000..19f0d033981
--- /dev/null
+++
b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/service/instrumentation/TestInstrumentationSerialization.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ozone.lib.service.instrumentation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.ozone.lib.service.Instrumentation;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Verifies that the {@code @JsonValue}-annotated snapshot types in
+ * {@link InstrumentationService} serialize to the same JSON shape that the
+ * former json-simple based serialization produced.
+ */
+public class TestInstrumentationSerialization {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ @Test
+ public void testTimerSerialization() {
+ InstrumentationService.Cron cron = new InstrumentationService.Cron();
+ cron.start();
+ cron.stop();
+ InstrumentationService.Timer timer = new InstrumentationService.Timer(10);
+ timer.addCron(cron);
+
+ JsonNode node = MAPPER.valueToTree(timer);
+ assertThat(node.isObject()).isTrue();
+ assertThat(node.fieldNames()).toIterable()
+ .containsExactly("lastTotal", "lastOwn", "avgTotal", "avgOwn");
+ assertThat(node.get("lastTotal").isNumber()).isTrue();
+ assertThat(node.get("avgOwn").isNumber()).isTrue();
+ }
+
+ @Test
+ public void testVariableHolderSerialization() {
+ InstrumentationService.VariableHolder<Long> holder =
+ new InstrumentationService.VariableHolder<>(
+ (Instrumentation.Variable<Long>) () -> 42L);
+
+ JsonNode node = MAPPER.valueToTree(holder);
+ assertThat(node.isObject()).isTrue();
+ assertThat(node.fieldNames()).toIterable().containsExactly("value");
+ assertThat(node.get("value").asLong()).isEqualTo(42L);
+ }
+
+ @Test
+ public void testSamplerSerialization() {
+ InstrumentationService.Sampler sampler =
+ new InstrumentationService.Sampler();
+ sampler.init(4, () -> 7L);
+ sampler.sample();
+
+ JsonNode node = MAPPER.valueToTree(sampler);
+ assertThat(node.isObject()).isTrue();
+ assertThat(node.fieldNames()).toIterable()
+ .containsExactly("sampler", "size");
+ assertThat(node.get("sampler").isNumber()).isTrue();
+ assertThat(node.get("size").asInt()).isEqualTo(1);
+ }
+}
diff --git
a/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/wsrs/TestJSONMapProvider.java
b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/wsrs/TestJSONMapProvider.java
new file mode 100644
index 00000000000..606f3145430
--- /dev/null
+++
b/hadoop-ozone/httpfsgateway/src/test/java/org/apache/ozone/lib/wsrs/TestJSONMapProvider.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ozone.lib.wsrs;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link JSONMapProvider} JSON output framing after the json-simple to
+ * Jackson migration.
+ */
+public class TestJSONMapProvider {
+
+ private String writeToString(Map<String, Object> map, ByteArrayOutputStream
out)
+ throws IOException {
+ new JSONMapProvider().writeTo(map, Map.class, Map.class, null, null, null,
out);
+ return new String(out.toByteArray(), StandardCharsets.UTF_8);
+ }
+
+ @Test
+ public void testWriteToEmitsJsonWithTrailingNewline() throws IOException {
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("boolean", true);
+ map.put("long", 42L);
+ map.put("string", "value");
+
+ String output = writeToString(map, new ByteArrayOutputStream());
+ assertThat(output).isEqualTo(
+ "{\"boolean\":true,\"long\":42,\"string\":\"value\"}"
+ + System.getProperty("line.separator"));
+ }
+
+ @Test
+ public void testWriteToDoesNotCloseUnderlyingStream() throws IOException {
+ AtomicBoolean closed = new AtomicBoolean(false);
+ ByteArrayOutputStream out = new ByteArrayOutputStream() {
+ @Override
+ public void close() {
+ closed.set(true);
+ }
+ };
+
+ Map<String, Object> map = new LinkedHashMap<>();
+ map.put("k", "v");
+ writeToString(map, out);
+
+ assertThat(closed).isFalse();
+ }
+}
diff --git a/pom.xml b/pom.xml
index 093e0519875..ba1b1ea64b7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -118,7 +118,6 @@
<joda.time.version>2.12.7</joda.time.version>
<jooq.version>3.11.10</jooq.version>
<jsch.version>0.1.55</jsch.version>
- <json-simple.version>1.1.1</json-simple.version>
<jsp-api.version>2.1</jsp-api.version>
<jsr311-api.version>1.1.1</jsr311-api.version>
<junit5.version>5.14.4</junit5.version>
@@ -456,11 +455,6 @@
<artifactId>compile-testing</artifactId>
<version>${compile-testing.version}</version>
</dependency>
- <dependency>
- <groupId>com.googlecode.json-simple</groupId>
- <artifactId>json-simple</artifactId>
- <version>${json-simple.version}</version>
- </dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]