diff --git a/scylla-apiclient/pom.xml b/scylla-apiclient/pom.xml
index 184d215..272692b 100644
--- a/scylla-apiclient/pom.xml
+++ b/scylla-apiclient/pom.xml
@@ -60,6 +60,21 @@
activation
1.1
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.9.9
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.9.9
+
+
+ com.fasterxml.jackson.jaxrs
+ jackson-jaxrs-json-provider
+ 2.9.9
+
diff --git a/scylla-apiclient/src/main/java/com/scylladb/jmx/api/APIClient.java b/scylla-apiclient/src/main/java/com/scylladb/jmx/api/APIClient.java
index 86ae4f4..dc6903e 100644
--- a/scylla-apiclient/src/main/java/com/scylladb/jmx/api/APIClient.java
+++ b/scylla-apiclient/src/main/java/com/scylladb/jmx/api/APIClient.java
@@ -38,6 +38,7 @@ import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import com.scylladb.jmx.utils.SnapshotDetailsTabularData;
public class APIClient {
@@ -78,9 +79,12 @@ public class APIClient {
private static final Logger logger = Logger.getLogger(APIClient.class.getName());
private final APIConfig config;
+ private final ClientConfig clientConfig;
public APIClient(APIConfig config) {
this.config = config;
+ this.clientConfig = new ClientConfig();
+ clientConfig.register(new JacksonJaxbJsonProvider());
}
private String getBaseUrl() {
@@ -88,7 +92,7 @@ public class APIClient {
}
public Invocation.Builder get(String path, MultivaluedMap queryParams) {
- Client client = ClientBuilder.newClient(new ClientConfig());
+ Client client = ClientBuilder.newClient(clientConfig);
WebTarget webTarget = client.target(getBaseUrl()).path(path);
if (queryParams != null) {
for (Entry> qp : queryParams.entrySet()) {
diff --git a/src/main/java/com/scylladb/jmx/utils/DateXmlAdapter.java b/src/main/java/com/scylladb/jmx/utils/DateXmlAdapter.java
new file mode 100644
index 0000000..572cec9
--- /dev/null
+++ b/src/main/java/com/scylladb/jmx/utils/DateXmlAdapter.java
@@ -0,0 +1,19 @@
+package com.scylladb.jmx.utils;
+
+import java.time.Instant;
+import java.util.Date;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+public class DateXmlAdapter extends XmlAdapter {
+ @Override
+ public String marshal(Date v) throws Exception {
+ return Instant.ofEpochMilli(v.getTime()).toString();
+ }
+
+ @Override
+ public Date unmarshal(String v) throws Exception {
+ return new Date(Instant.parse(v).toEpochMilli());
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/cassandra/service/PerTableSSTableInfo.java b/src/main/java/org/apache/cassandra/service/PerTableSSTableInfo.java
new file mode 100644
index 0000000..bfcd4fd
--- /dev/null
+++ b/src/main/java/org/apache/cassandra/service/PerTableSSTableInfo.java
@@ -0,0 +1,66 @@
+package org.apache.cassandra.service;
+
+import static com.sun.jmx.mbeanserver.MXBeanMappingFactory.DEFAULT;
+
+import java.io.InvalidObjectException;
+import java.util.List;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.OpenDataException;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.sun.jmx.mbeanserver.MXBeanMapping;
+
+@SuppressWarnings("restriction")
+@XmlRootElement
+public class PerTableSSTableInfo {
+ private static final MXBeanMapping mxBeanMapping;
+
+ static {
+ try {
+ mxBeanMapping = DEFAULT.mappingForType(PerTableSSTableInfo.class, DEFAULT);
+ } catch (OpenDataException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String keyspace;
+ private List sstables;
+ private String table;
+
+ public String getTable() {
+ return table;
+ }
+
+ public void setTable(String table) {
+ this.table = table;
+ }
+
+ public String getKeyspace() {
+ return keyspace;
+ }
+
+ public void setKeyspace(String keyspace) {
+ this.keyspace = keyspace;
+ }
+
+ public List getSSTables() {
+ return sstables;
+ }
+
+ public void setSSTableInfos(List sstableInfos) {
+ this.sstables = sstableInfos;
+ }
+
+ public CompositeData toCompositeData() {
+ try {
+ return (CompositeData) mxBeanMapping.toOpenValue(this);
+ } catch (OpenDataException e) {
+ throw new Error(e); // should not reach.
+ }
+ }
+
+ public static PerTableSSTableInfo from(CompositeData data) throws InvalidObjectException {
+ return (PerTableSSTableInfo) mxBeanMapping.fromOpenValue(data);
+ }
+}
diff --git a/src/main/java/org/apache/cassandra/service/SSTableInfo.java b/src/main/java/org/apache/cassandra/service/SSTableInfo.java
new file mode 100644
index 0000000..17287c8
--- /dev/null
+++ b/src/main/java/org/apache/cassandra/service/SSTableInfo.java
@@ -0,0 +1,143 @@
+package org.apache.cassandra.service;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.scylladb.jmx.utils.DateXmlAdapter;
+
+public class SSTableInfo {
+ private long size;
+
+ @JsonProperty("data_size")
+ private long dataSize;
+
+ @JsonProperty("index_size")
+ private long indexSize;
+
+ @JsonProperty("filter_size")
+ private long filterSize;
+
+ @XmlJavaTypeAdapter(type = Date.class, value = DateXmlAdapter.class)
+ private Date timestamp;
+
+ private long generation;
+
+ private long level;
+
+ private String version;
+
+ private Map properties;
+
+ public void setProperties(Map properties) {
+ this.properties = properties;
+ }
+
+ @JsonIgnore
+ private Map> extendedProperties;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+
+ public long getDataSize() {
+ return dataSize;
+ }
+
+ public void setDataSize(long dataSize) {
+ this.dataSize = dataSize;
+ }
+
+ public long getIndexSize() {
+ return indexSize;
+ }
+
+ public void setIndexSize(long indexSize) {
+ this.indexSize = indexSize;
+ }
+
+ public long getFilterSize() {
+ return filterSize;
+ }
+
+ public void setFilterSize(long filterSize) {
+ this.filterSize = filterSize;
+ }
+
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Date timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public long getGeneration() {
+ return generation;
+ }
+
+ public void setGeneration(long generation) {
+ this.generation = generation;
+ }
+
+ public long getLevel() {
+ return level;
+ }
+
+ public void setLevel(long level) {
+ this.level = level;
+ }
+
+ public Map getProperties() {
+ return properties;
+ }
+
+ public Map> getExtendedProperties() {
+ return extendedProperties;
+ }
+
+ public void setExtendedProperties(Map> extendedProperties) {
+ this.extendedProperties = extendedProperties;
+ }
+
+ @JsonProperty("extended_properties")
+ private void unpackNested(List