Refactor license serialization/deserialization

Original commit: elastic/x-pack-elasticsearch@ac0bb4a147
This commit is contained in:
Igor Motov 2014-10-27 20:04:09 -04:00
parent a57164ec67
commit 61b1750058
4 changed files with 168 additions and 100 deletions

View File

@ -5,15 +5,17 @@
*/ */
package org.elasticsearch.license.core; package org.elasticsearch.license.core;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ESLicense implements Comparable<ESLicense> { public class ESLicense implements Comparable<ESLicense>, ToXContent {
private final String uid; private final String uid;
private final String issuer; private final String issuer;
@ -117,6 +119,129 @@ public class ESLicense implements Comparable<ESLicense> {
return Long.compare(expiryDate, o.expiryDate); return Long.compare(expiryDate, o.expiryDate);
} }
static ESLicense readESLicense(StreamInput in) throws IOException {
in.readVInt(); // Version for future extensibility
Builder builder = builder();
builder.uid(in.readString());
builder.type(Type.fromString(in.readString()));
builder.subscriptionType(SubscriptionType.fromString(in.readString()));
builder.issueDate(in.readLong());
builder.feature(in.readString());
builder.expiryDate(in.readLong());
builder.maxNodes(in.readInt());
builder.issuedTo(in.readString());
builder.issuer(in.readString());
builder.signature(in.readOptionalString());
return builder.verifyAndBuild();
}
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(VERSION);
out.writeString(uid);
out.writeString(type.string());
out.writeString(subscriptionType.string());
out.writeLong(issueDate);
out.writeString(feature);
out.writeLong(expiryDate);
out.writeInt(maxNodes);
out.writeString(issuedTo);
out.writeString(issuer);
out.writeOptionalString(signature);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(XFields.UID, uid);
builder.field(XFields.TYPE, type.string());
builder.field(XFields.SUBSCRIPTION_TYPE, subscriptionType.string());
builder.field(XFields.ISSUE_DATE, issueDate);
builder.field(XFields.FEATURE, feature);
builder.field(XFields.EXPIRY_DATE, expiryDate);
builder.field(XFields.MAX_NODES, maxNodes);
builder.field(XFields.ISSUED_TO, issuedTo);
builder.field(XFields.ISSUER, issuer);
if (signature != null) {
builder.field(XFields.SIGNATURE, signature);
}
builder.endObject();
return builder;
}
private final static int VERSION = 1;
final static class Fields {
static final String UID = "uid";
static final String TYPE = "type";
static final String SUBSCRIPTION_TYPE = "subscription_type";
static final String ISSUE_DATE = "issue_date";
static final String FEATURE = "feature";
static final String EXPIRY_DATE = "expiry_date";
static final String MAX_NODES = "max_nodes";
static final String ISSUED_TO = "issued_to";
static final String ISSUER = "issuer";
static final String SIGNATURE = "signature";
}
private final static class XFields {
static final XContentBuilderString UID = new XContentBuilderString(Fields.UID);
static final XContentBuilderString TYPE = new XContentBuilderString(Fields.TYPE);
static final XContentBuilderString SUBSCRIPTION_TYPE = new XContentBuilderString(Fields.SUBSCRIPTION_TYPE);
static final XContentBuilderString ISSUE_DATE = new XContentBuilderString(Fields.ISSUE_DATE);
static final XContentBuilderString FEATURE = new XContentBuilderString(Fields.FEATURE);
static final XContentBuilderString EXPIRY_DATE = new XContentBuilderString(Fields.EXPIRY_DATE);
static final XContentBuilderString MAX_NODES = new XContentBuilderString(Fields.MAX_NODES);
static final XContentBuilderString ISSUED_TO = new XContentBuilderString(Fields.ISSUED_TO);
static final XContentBuilderString ISSUER = new XContentBuilderString(Fields.ISSUER);
static final XContentBuilderString SIGNATURE = new XContentBuilderString(Fields.SIGNATURE);
}
public static ESLicense fromXContent(XContentParser parser) throws IOException {
Builder builder = new Builder();
XContentParser.Token token = parser.currentToken();
if (token == XContentParser.Token.START_OBJECT) {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
String currentFieldName = parser.currentName();
token = parser.nextToken();
if (token.isValue()) {
if (Fields.UID.equals(currentFieldName)) {
builder.uid(parser.text());
} else if (Fields.TYPE.equals(currentFieldName)) {
builder.type(Type.fromString(parser.text()));
} else if (Fields.SUBSCRIPTION_TYPE.equals(currentFieldName)) {
builder.subscriptionType(SubscriptionType.fromString(parser.text()));
} else if (Fields.ISSUE_DATE.equals(currentFieldName)) {
builder.issueDate(parser.longValue());
} else if (Fields.FEATURE.equals(currentFieldName)) {
builder.feature(parser.text());
} else if (Fields.EXPIRY_DATE.equals(currentFieldName)) {
builder.expiryDate(parser.longValue());
} else if (Fields.MAX_NODES.equals(currentFieldName)) {
builder.maxNodes(parser.intValue());
} else if (Fields.ISSUED_TO.equals(currentFieldName)) {
builder.issuedTo(parser.text());
} else if (Fields.ISSUER.equals(currentFieldName)) {
builder.issuer(parser.text());
} else if (Fields.SIGNATURE.equals(currentFieldName)) {
builder.signature(parser.text());
}
// Ignore unknown elements - might be new version of license
} else if (token == XContentParser.Token.START_ARRAY) {
// It was probably created by newer version - ignoring
parser.skipChildren();
} else if (token == XContentParser.Token.START_OBJECT) {
// It was probably created by newer version - ignoring
parser.skipChildren();
}
}
}
} else {
throw new ElasticsearchParseException("failed to parse licenses expected a license object");
}
return builder.verifyAndBuild();
}
/** /**
* Enum for License Type * Enum for License Type
*/ */
@ -306,81 +431,4 @@ public class ESLicense implements Comparable<ESLicense> {
} }
} }
final static class Fields {
static final String UID = "uid";
static final String TYPE = "type";
static final String SUBSCRIPTION_TYPE = "subscription_type";
static final String ISSUE_DATE = "issue_date";
static final String FEATURE = "feature";
static final String EXPIRY_DATE = "expiry_date";
static final String MAX_NODES = "max_nodes";
static final String ISSUED_TO = "issued_to";
static final String ISSUER = "issuer";
static final String SIGNATURE = "signature";
}
static void toXContent(ESLicense license, XContentBuilder builder) throws IOException {
builder.startObject();
builder.field(Fields.UID, license.uid);
builder.field(Fields.TYPE, license.type.string());
builder.field(Fields.SUBSCRIPTION_TYPE, license.subscriptionType.string());
builder.field(Fields.ISSUE_DATE, license.issueDate);
builder.field(Fields.FEATURE, license.feature);
builder.field(Fields.EXPIRY_DATE, license.expiryDate);
builder.field(Fields.MAX_NODES, license.maxNodes);
builder.field(Fields.ISSUED_TO, license.issuedTo);
builder.field(Fields.ISSUER, license.issuer);
builder.field(Fields.SIGNATURE, license.signature);
builder.endObject();
}
static ESLicense fromXContent(Map<String, Object> map) throws IOException {
return new Builder()
.uid((String) map.get(Fields.UID))
.type(Type.fromString((String) map.get(Fields.TYPE)))
.subscriptionType(SubscriptionType.fromString((String) map.get(Fields.SUBSCRIPTION_TYPE)))
.feature((String) map.get(Fields.FEATURE))
.maxNodes((int) map.get(Fields.MAX_NODES))
.issuedTo((String) map.get(Fields.ISSUED_TO))
.signature((String) map.get(Fields.SIGNATURE))
.issueDate((long) map.get(Fields.ISSUE_DATE))
.expiryDate((long) map.get(Fields.EXPIRY_DATE))
.issuer((String) map.get(Fields.ISSUER))
.verifyAndBuild();
}
static ESLicense readFrom(StreamInput in) throws IOException {
Map<String, Object> licenseMap = in.readMap();
return builder()
.uid((String) licenseMap.get(Fields.UID))
.type(Type.fromString((String) licenseMap.get(Fields.TYPE)))
.subscriptionType(SubscriptionType.fromString((String) licenseMap.get(Fields.SUBSCRIPTION_TYPE)))
.issueDate((long) licenseMap.get(Fields.ISSUE_DATE))
.feature((String) licenseMap.get(Fields.FEATURE))
.expiryDate((long) licenseMap.get(Fields.EXPIRY_DATE))
.maxNodes((int) licenseMap.get(Fields.MAX_NODES))
.issuedTo((String) licenseMap.get(Fields.ISSUED_TO))
.signature((String) licenseMap.get(Fields.SIGNATURE))
.issuer((String) licenseMap.get(Fields.ISSUER))
.verifyAndBuild();
}
static void writeTo(ESLicense esLicense, StreamOutput out) throws IOException {
Map<String, Object> licenseMap = new HashMap<>();
licenseMap.put(Fields.UID, esLicense.uid);
licenseMap.put(Fields.TYPE, esLicense.type.string());
licenseMap.put(Fields.SUBSCRIPTION_TYPE, esLicense.subscriptionType.string());
licenseMap.put(Fields.ISSUE_DATE, esLicense.issueDate);
licenseMap.put(Fields.FEATURE, esLicense.feature);
licenseMap.put(Fields.EXPIRY_DATE, esLicense.expiryDate);
licenseMap.put(Fields.MAX_NODES, esLicense.maxNodes);
licenseMap.put(Fields.ISSUED_TO, esLicense.issuedTo);
licenseMap.put(Fields.ISSUER, esLicense.issuer);
licenseMap.put(Fields.SIGNATURE, esLicense.signature);
out.writeMap(licenseMap);
}
} }

View File

@ -5,23 +5,30 @@
*/ */
package org.elasticsearch.license.core; package org.elasticsearch.license.core;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.*;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
public class ESLicenses { public class ESLicenses {
public static void toXContent(Collection<ESLicense> licenses, XContentBuilder builder) throws IOException { final static class Fields {
static final String LICENSES = "licenses";
}
private final static class XFields {
static final XContentBuilderString LICENSES = new XContentBuilderString(Fields.LICENSES);
}
public static void toXContent(Collection<ESLicense> licenses, XContentBuilder builder, ToXContent.Params params) throws IOException {
builder.startObject(); builder.startObject();
builder.startArray("licenses"); builder.startArray(XFields.LICENSES);
for (ESLicense license : licenses) { for (ESLicense license : licenses) {
ESLicense.toXContent(license, builder); license.toXContent(builder, params);
} }
builder.endArray(); builder.endArray();
builder.endObject(); builder.endObject();
@ -35,23 +42,35 @@ public class ESLicenses {
return fromXContent(XContentFactory.xContent(bytes).createParser(bytes)); return fromXContent(XContentFactory.xContent(bytes).createParser(bytes));
} }
private static List<ESLicense> fromXContent(XContentParser parser) throws IOException { public static List<ESLicense> fromXContent(XContentParser parser) throws IOException {
Set<ESLicense> esLicenses = new HashSet<>(); List<ESLicense> esLicenses = new ArrayList<>();
final Map<String, Object> licensesMap = parser.mapAndClose(); if (parser.nextToken() == XContentParser.Token.START_OBJECT) {
@SuppressWarnings("unchecked") if (parser.nextToken() == XContentParser.Token.FIELD_NAME) {
final List<Map<String, Object>> licenseMaps = (ArrayList<Map<String, Object>>)licensesMap.get("licenses"); String currentFieldName = parser.currentName();
for (Map<String, Object> licenseMap : licenseMaps) { if (Fields.LICENSES.equals(currentFieldName)) {
final ESLicense esLicense = ESLicense.fromXContent(licenseMap); if (parser.nextToken() == XContentParser.Token.START_ARRAY) {
esLicenses.add(esLicense); while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
esLicenses.add(ESLicense.fromXContent(parser));
}
} else {
throw new ElasticsearchParseException("failed to parse licenses expected an array of licenses");
}
}
// Ignore all other fields - might be created with new version
} else {
throw new ElasticsearchParseException("failed to parse licenses expected field");
}
} else {
throw new ElasticsearchParseException("failed to parse licenses expected start object");
} }
return new ArrayList<>(esLicenses); return esLicenses;
} }
public static List<ESLicense> readFrom(StreamInput in) throws IOException { public static List<ESLicense> readFrom(StreamInput in) throws IOException {
int size = in.readVInt(); int size = in.readVInt();
List<ESLicense> esLicenses = new ArrayList<>(size); List<ESLicense> esLicenses = new ArrayList<>(size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
esLicenses.add(ESLicense.readFrom(in)); esLicenses.add(ESLicense.readESLicense(in));
} }
return esLicenses; return esLicenses;
} }
@ -59,9 +78,8 @@ public class ESLicenses {
public static void writeTo(List<ESLicense> esLicenses, StreamOutput out) throws IOException { public static void writeTo(List<ESLicense> esLicenses, StreamOutput out) throws IOException {
out.writeVInt(esLicenses.size()); out.writeVInt(esLicenses.size());
for (ESLicense license : esLicenses) { for (ESLicense license : esLicenses) {
ESLicense.writeTo(license, out); license.writeTo(out);
} }
} }
public static ImmutableMap<String, ESLicense> reduceAndMap(Set<ESLicense> esLicensesSet) { public static ImmutableMap<String, ESLicense> reduceAndMap(Set<ESLicense> esLicensesSet) {

View File

@ -6,6 +6,7 @@
package org.elasticsearch.license.licensor.tools; package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.common.collect.ImmutableSet; import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -93,7 +94,7 @@ public class LicenseGeneratorTool {
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out); XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out);
ESLicenses.toXContent(signedLicences, builder); ESLicenses.toXContent(signedLicences, builder, ToXContent.EMPTY_PARAMS);
builder.flush(); builder.flush();
} }

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.license.licensor.tools; package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -80,7 +81,7 @@ public class LicenseVerificationTool {
// dump effective licences // dump effective licences
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out); XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out);
ESLicenses.toXContent(licenseProvider.getEffectiveLicenses().values(), builder); ESLicenses.toXContent(licenseProvider.getEffectiveLicenses().values(), builder, ToXContent.EMPTY_PARAMS);
builder.flush(); builder.flush();
} }