All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.license.License Maven / Gradle / Ivy

There is a newer version: 8.16.0
Show newest version
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0; you may not use this file except in compliance with the Elastic License
 * 2.0.
 */
package org.elasticsearch.license;

import org.apache.lucene.util.CollectionUtil;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.features.NodeFeature;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Data structure for license. Use {@link Builder} to build a license.
 * Provides serialization/deserialization & validation methods for license object
 */
public class License implements ToXContentObject {

    public static final NodeFeature INDEPENDENT_TRIAL_VERSION_FEATURE = new NodeFeature("license-trial-independent-version");

    public enum LicenseType {
        BASIC,
        STANDARD,
        GOLD,
        PLATINUM,
        ENTERPRISE,
        TRIAL;

        public String getTypeName() {
            return name().toLowerCase(Locale.ROOT);
        }

        public static LicenseType parse(String type) throws IllegalArgumentException {
            try {
                return LicenseType.valueOf(type.toUpperCase(Locale.ROOT));
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(
                    "unrecognised license type [ "
                        + type
                        + "], supported license types are ["
                        + Stream.of(values()).map(LicenseType::getTypeName).collect(Collectors.joining(","))
                        + "]"
                );
            }
        }

        /**
         * Backward compatible license type parsing for older license models
         */
        public static LicenseType resolve(License license) {
            if (license.version == VERSION_START) {
                // in 1.x: the acceptable values for 'subscription_type': none | dev | silver | gold | platinum
                return resolve(license.subscriptionType);
            } else {
                // in 2.x: the acceptable values for 'type': trial | basic | silver | dev | gold | platinum
                // in 5.x: the acceptable values for 'type': trial | basic | standard | dev | gold | platinum
                // in 6.x: the acceptable values for 'type': trial | basic | standard | dev | gold | platinum
                // in 7.x: the acceptable values for 'type': trial | basic | standard | dev | gold | platinum | enterprise
                return resolve(license.type);
            }
        }

        /**
         * Backward compatible license type parsing for older license models
         */
        static LicenseType resolve(String name) {
            return switch (name.toLowerCase(Locale.ROOT)) {
                case "missing" -> null; // bwc for 1.x subscription_type field
                // bwc for 1.x subscription_type field
                case "trial", "none", "dev", "development" -> // bwc for 1.x subscription_type field
                    TRIAL;
                case "basic" -> BASIC;
                case "standard" -> STANDARD;
                case "silver", "gold" -> GOLD;
                case "platinum", "internal" -> // bwc for 1.x subscription_type field
                    PLATINUM;
                case "enterprise" -> ENTERPRISE;
                default -> throw new IllegalArgumentException("unknown license type [" + name + "]");
            };
        }

        static boolean isBasic(String typeName) {
            return BASIC.getTypeName().equals(typeName);
        }

        static boolean isTrial(String typeName) {
            return TRIAL.getTypeName().equals(typeName);
        }

        static boolean isEnterprise(String typeName) {
            return ENTERPRISE.getTypeName().equals(typeName);
        }

    }

    public static final int VERSION_START = 1;
    public static final int VERSION_NO_FEATURE_TYPE = 2;
    public static final int VERSION_START_DATE = 3;
    public static final int VERSION_CRYPTO_ALGORITHMS = 4;
    public static final int VERSION_ENTERPRISE = 5;
    public static final int VERSION_CURRENT = VERSION_ENTERPRISE;

    /**
     * XContent param name to deserialize license(s) with
     * an additional status field, indicating whether a
     * particular license is 'active' or 'expired' and no signature
     * and in a human readable format
     */
    public static final String REST_VIEW_MODE = "rest_view";
    /**
     * XContent param name to deserialize license(s) with
     * no signature
     */
    public static final String LICENSE_SPEC_VIEW_MODE = "license_spec_view";
    /**
     * XContent param name to deserialize licenses according
     * to a specific license version
     */
    public static final String LICENSE_VERSION_MODE = "license_version";
    /**
     * Set for {@link RestApiVersion#V_7} requests only
     * XContent param name to map the "enterprise" license type to "platinum"
     * for backwards compatibility with older clients
     */
    public static final String XCONTENT_HIDE_ENTERPRISE = "hide_enterprise";

    public static final Comparator LATEST_ISSUE_DATE_FIRST = Comparator.comparing(License::issueDate).reversed();

    private final int version;
    private final String uid;
    private final String issuer;
    private final String issuedTo;
    private final long issueDate;
    private final String type;
    private final String subscriptionType;
    private final String feature;
    private final String signature;
    private final long expiryDate;
    private final long startDate;
    private final int maxNodes;
    private final int maxResourceUnits;
    private final OperationMode operationMode;

    /**
     * Decouples operation mode of a license from the license type value.
     * 

* Note: The mode indicates features that should be made available, but it does not indicate whether the license is active! *

* The id byte is used for ordering operation modes */ public enum OperationMode { MISSING((byte) 0), TRIAL((byte) 1), BASIC((byte) 2), STANDARD((byte) 3), GOLD((byte) 4), PLATINUM((byte) 5), ENTERPRISE((byte) 6); private final byte id; OperationMode(byte id) { this.id = id; } /** * Returns non-zero positive number when opMode1 is greater than opMode2 */ public static int compare(OperationMode opMode1, OperationMode opMode2) { return Integer.compare(opMode1.id, opMode2.id); } /** * Determine the operating mode for a license type * * @see LicenseType#resolve(License) * @see #parse(String) */ public static OperationMode resolve(LicenseType type) { if (type == null) { return MISSING; } return switch (type) { case BASIC -> BASIC; case STANDARD -> STANDARD; case GOLD -> GOLD; case PLATINUM -> PLATINUM; case ENTERPRISE -> ENTERPRISE; case TRIAL -> TRIAL; }; } /** * Parses an {@code OperatingMode} from a String. * The string must name an operating mode, and not a licensing level (that is, it cannot parse old style license levels * such as "dev" or "silver"). * * @see #description() */ public static OperationMode parse(String mode) { try { return OperationMode.valueOf(mode.toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( "unrecognised license operating mode [ " + mode + "], supported modes are [" + Stream.of(values()).map(OperationMode::description).collect(Collectors.joining(",")) + "]" ); } } public String description() { return name().toLowerCase(Locale.ROOT); } } private License( int version, String uid, String issuer, String issuedTo, long issueDate, String type, String subscriptionType, String feature, String signature, long expiryDate, int maxNodes, int maxResourceUnits, long startDate ) { this.version = version; this.uid = uid; this.issuer = issuer; this.issuedTo = issuedTo; this.issueDate = issueDate; this.type = type; this.subscriptionType = subscriptionType; this.feature = feature; this.signature = signature; // We will validate that only a basic license can have the BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS // in the validate() method. if (expiryDate == -1) { this.expiryDate = LicenseSettings.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS; } else { this.expiryDate = expiryDate; } this.maxNodes = maxNodes; this.maxResourceUnits = maxResourceUnits; this.startDate = startDate; this.operationMode = OperationMode.resolve(LicenseType.resolve(this)); validate(); } /** * @return version of the license */ public int version() { return version; } /** * @return a unique identifier for a license */ public String uid() { return uid; } /** * @return type of the license [trial, subscription, internal] */ public String type() { return type; } /** * @return the issueDate in milliseconds */ public long issueDate() { return issueDate; } /** * @return the startDate in milliseconds */ public long startDate() { return startDate; } /** * The expiration date as it appears in the license. For most uses, prefer {@link LicenseUtils#getExpiryDate(License)}, as in * rare cases the effective expiration date may differ from the expiration date specified in the license. * * @return the expiry date in milliseconds */ public long expiryDate() { return expiryDate; } /** * @return the maximum number of nodes this license has been issued for, or {@code -1} if this license is not node based. */ public int maxNodes() { return maxNodes; } /** * @return the maximum number of "resource units" this license has been issued for, or {@code -1} if this license is not resource based. * A "resource unit" is a measure of computing power (RAM/CPU), the definition of which is maintained outside of the license format, * or this class. */ public int maxResourceUnits() { return maxResourceUnits; } /** * @return a string representing the entity this licenses has been issued to */ public String issuedTo() { return issuedTo; } /** * @return a string representing the entity responsible for issuing this license (internal) */ public String issuer() { return issuer; } /** * @return a string representing the signature of the license used for license verification */ public String signature() { return signature; } /** * @return the operation mode of the license as computed from the license type */ public OperationMode operationMode() { return operationMode; } private void validate() { if (issuer == null) { throw new IllegalStateException("issuer can not be null"); } else if (issuedTo == null) { throw new IllegalStateException("issuedTo can not be null"); } else if (issueDate == -1) { throw new IllegalStateException("issueDate has to be set"); } else if (type == null) { throw new IllegalStateException("type can not be null"); } else if (subscriptionType == null && version == VERSION_START) { throw new IllegalStateException("subscriptionType can not be null"); } else if (uid == null) { throw new IllegalStateException("uid can not be null"); } else if (feature == null && version == VERSION_START) { throw new IllegalStateException("feature can not be null"); } else if (expiryDate == -1) { throw new IllegalStateException("expiryDate has to be set"); } else if (expiryDate == LicenseSettings.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS && LicenseType.isBasic(type) == false) { throw new IllegalStateException("only basic licenses are allowed to have no expiration"); } if (LicenseType.isEnterprise(type) && version < VERSION_ENTERPRISE) { throw new IllegalStateException("license type [" + type + "] is not a valid for version [" + version + "] licenses"); } validateLimits(type, maxNodes, maxResourceUnits); } private static void validateLimits(String type, int maxNodes, int maxResourceUnits) { if (LicenseType.isEnterprise(type)) { if (maxResourceUnits == -1) { throw new IllegalStateException("maxResourceUnits must be set for enterprise licenses (type=[" + type + "])"); } else if (maxNodes != -1) { throw new IllegalStateException("maxNodes may not be set for enterprise licenses (type=[" + type + "])"); } } else { if (maxNodes == -1) { throw new IllegalStateException("maxNodes has to be set"); } else if (maxResourceUnits != -1) { throw new IllegalStateException( "maxResourceUnits may only be set for enterprise licenses (not permitted for type=[" + type + "])" ); } } } private Boolean isVerified; public boolean verified() { final Boolean v = isVerified; if (v != null) { return v; } final boolean verified = doVerify(); this.isVerified = verified; return verified; } private boolean doVerify() { boolean autoGeneratedLicense = License.isAutoGeneratedLicense(signature()); return (autoGeneratedLicense && SelfGeneratedLicense.verify(this)) || (autoGeneratedLicense == false && LicenseVerifier.verifyLicense(this)); } public static License readLicense(StreamInput in) throws IOException { int version = in.readVInt(); // Version for future extensibility if (version > VERSION_CURRENT) { throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest elasticsearch release"); } Builder builder = builder(); builder.version(version); builder.uid(in.readString()); builder.type(in.readString()); if (version == VERSION_START) { builder.subscriptionType(in.readString()); } builder.issueDate(in.readLong()); if (version == VERSION_START) { builder.feature(in.readString()); } builder.expiryDate(in.readLong()); builder.maxNodes(in.readInt()); if (version >= VERSION_ENTERPRISE) { builder.maxResourceUnits(in.readInt()); } builder.issuedTo(in.readString()); builder.issuer(in.readString()); builder.signature(in.readOptionalString()); if (version >= VERSION_START_DATE) { builder.startDate(in.readLong()); } return builder.build(); } public void writeTo(StreamOutput out) throws IOException { out.writeVInt(version); out.writeString(uid); out.writeString(type); if (version == VERSION_START) { out.writeString(subscriptionType); } out.writeLong(issueDate); if (version == VERSION_START) { out.writeString(feature); } out.writeLong(expiryDate); out.writeInt(maxNodes); if (version >= VERSION_ENTERPRISE) { out.writeInt(maxResourceUnits); } out.writeString(issuedTo); out.writeString(issuer); out.writeOptionalString(signature); if (version >= VERSION_START_DATE) { out.writeLong(startDate); } } @Override public String toString() { return Strings.toString(this); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); toInnerXContent(builder, params); builder.endObject(); return builder; } public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) throws IOException { boolean licenseSpecMode = params.paramAsBoolean(LICENSE_SPEC_VIEW_MODE, false); boolean restViewMode = params.paramAsBoolean(REST_VIEW_MODE, false); boolean hideEnterprise = params.paramAsBoolean(XCONTENT_HIDE_ENTERPRISE, false); boolean previouslyHumanReadable = builder.humanReadable(); if (licenseSpecMode && restViewMode) { throw new IllegalArgumentException("can have either " + REST_VIEW_MODE + " or " + LICENSE_SPEC_VIEW_MODE); } else if (restViewMode) { if (previouslyHumanReadable == false) { builder.humanReadable(true); } } final int licenseVersion; if (params.param(LICENSE_VERSION_MODE) != null && restViewMode) { licenseVersion = Integer.parseInt(params.param(LICENSE_VERSION_MODE)); } else { licenseVersion = this.version; } if (restViewMode) { builder.field(Fields.STATUS, LicenseUtils.status(this).label()); } builder.field(Fields.UID, uid); final String bwcType = hideEnterprise && LicenseType.isEnterprise(type) ? LicenseType.PLATINUM.getTypeName() : type; builder.field(Fields.TYPE, bwcType); if (licenseVersion == VERSION_START) { builder.field(Fields.SUBSCRIPTION_TYPE, subscriptionType); } builder.timeField(Fields.ISSUE_DATE_IN_MILLIS, Fields.ISSUE_DATE, issueDate); if (licenseVersion == VERSION_START) { builder.field(Fields.FEATURE, feature); } if (expiryDate != LicenseSettings.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS) { builder.timeField(Fields.EXPIRY_DATE_IN_MILLIS, Fields.EXPIRY_DATE, expiryDate); } if (licenseVersion >= VERSION_ENTERPRISE) { builder.field(Fields.MAX_NODES, maxNodes == -1 ? null : maxNodes); builder.field(Fields.MAX_RESOURCE_UNITS, maxResourceUnits == -1 ? null : maxResourceUnits); } else if (hideEnterprise && maxNodes == -1) { builder.field(Fields.MAX_NODES, maxResourceUnits); } else { builder.field(Fields.MAX_NODES, maxNodes); } builder.field(Fields.ISSUED_TO, issuedTo); builder.field(Fields.ISSUER, issuer); if (licenseSpecMode == false && restViewMode == false && signature != null) { builder.field(Fields.SIGNATURE, signature); } if (restViewMode) { builder.humanReadable(previouslyHumanReadable); } if (licenseVersion >= VERSION_START_DATE) { builder.timeField(Fields.START_DATE_IN_MILLIS, Fields.START_DATE, startDate); } return builder; } public static License fromXContent(XContentParser parser) throws IOException { Builder builder = new Builder(); XContentParser.Token token; 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(parser.text()); } else if (Fields.SUBSCRIPTION_TYPE.equals(currentFieldName)) { builder.subscriptionType(parser.text()); } else if (Fields.ISSUE_DATE.equals(currentFieldName)) { builder.issueDate(parseDate(parser, "issue", false)); } else if (Fields.ISSUE_DATE_IN_MILLIS.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(parseDate(parser, "expiration", true)); } else if (Fields.EXPIRY_DATE_IN_MILLIS.equals(currentFieldName)) { builder.expiryDate(parser.longValue()); } else if (Fields.START_DATE.equals(currentFieldName)) { builder.startDate(parseDate(parser, "start", false)); } else if (Fields.START_DATE_IN_MILLIS.equals(currentFieldName)) { builder.startDate(parser.longValue()); } else if (Fields.MAX_NODES.equals(currentFieldName)) { builder.maxNodes(parser.intValue()); } else if (Fields.MAX_RESOURCE_UNITS.equals(currentFieldName)) { builder.maxResourceUnits(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()); } else if (Fields.VERSION.equals(currentFieldName)) { builder.version(parser.intValue()); } // 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(); } } } // not a license spec if (builder.signature != null) { int version; // In case the signature is truncated/malformed we might end up with fewer than 4 bytes in the byteBuffer // or with a string that cannot be base64 decoded. In either case return a more friendly error instead of // just throwing the BufferUnderflowException or the IllegalArgumentException try { byte[] signatureBytes = Base64.getDecoder().decode(builder.signature); ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); version = byteBuffer.getInt(); } catch (Exception e) { throw new ElasticsearchParseException("malformed signature for license [" + builder.uid + "]", e); } // we take the absolute version, because negative versions // mean that the license was generated by the cluster (see TrialLicense) // and positive version means that the license was signed if (version < 0) { version *= -1; } if (version == 0) { throw new ElasticsearchParseException("malformed signature for license [" + builder.uid + "]"); } else if (version > VERSION_CURRENT) { throw new ElasticsearchParseException( "Unknown license version found, please upgrade all nodes to the latest " + "elasticsearch-license plugin" ); } // signature version is the source of truth builder.version(version); } return builder.build(); } /** * Returns true if the license was auto-generated (by license plugin), * false otherwise */ public static boolean isAutoGeneratedLicense(String signature) { try { byte[] signatureBytes = Base64.getDecoder().decode(signature); ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); return byteBuffer.getInt() < 0; } catch (IllegalArgumentException e) { throw new IllegalStateException(e); } } public static License fromSource(BytesReference bytes, XContentType xContentType) throws IOException { if (bytes == null || bytes.length() == 0) { throw new ElasticsearchParseException("failed to parse license - no content provided"); } if (xContentType == null) { throw new ElasticsearchParseException("failed to parse license - no content-type provided"); } // EMPTY is safe here because we don't call namedObject try ( XContentParser parser = XContentHelper.createParserNotCompressed( LoggingDeprecationHandler.XCONTENT_PARSER_CONFIG, bytes, xContentType ) ) { License license = null; if (parser.nextToken() == XContentParser.Token.START_OBJECT) { if (parser.nextToken() == XContentParser.Token.FIELD_NAME) { String currentFieldName = parser.currentName(); if (Fields.LICENSES.equals(currentFieldName)) { final List pre20Licenses = new ArrayList<>(); if (parser.nextToken() == XContentParser.Token.START_ARRAY) { while (parser.nextToken() != XContentParser.Token.END_ARRAY) { pre20Licenses.add(License.fromXContent(parser)); } // take the latest issued unexpired license CollectionUtil.timSort(pre20Licenses, LATEST_ISSUE_DATE_FIRST); long now = System.currentTimeMillis(); for (License oldLicense : pre20Licenses) { if (oldLicense.expiryDate() > now) { license = oldLicense; break; } } if (license == null && pre20Licenses.isEmpty() == false) { license = pre20Licenses.get(0); } } else { throw new ElasticsearchParseException("failed to parse licenses expected an array of licenses"); } } else if (Fields.LICENSE.equals(currentFieldName)) { license = License.fromXContent(parser); } // 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 license; } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; License license = (License) o; if (issueDate != license.issueDate) return false; if (expiryDate != license.expiryDate) return false; if (startDate != license.startDate) return false; if (maxNodes != license.maxNodes) return false; if (version != license.version) return false; return Objects.equals(uid, license.uid) && Objects.equals(issuer, license.issuer) && Objects.equals(issuedTo, license.issuedTo) && Objects.equals(type, license.type) && Objects.equals(subscriptionType, license.subscriptionType) && Objects.equals(feature, license.feature) && Objects.equals(signature, license.signature); } @Override public int hashCode() { int result = uid != null ? uid.hashCode() : 0; result = 31 * result + (issuer != null ? issuer.hashCode() : 0); result = 31 * result + (issuedTo != null ? issuedTo.hashCode() : 0); result = 31 * result + (int) (issueDate ^ (issueDate >>> 32)); result = 31 * result + (type != null ? type.hashCode() : 0); result = 31 * result + (subscriptionType != null ? subscriptionType.hashCode() : 0); result = 31 * result + (feature != null ? feature.hashCode() : 0); result = 31 * result + (signature != null ? signature.hashCode() : 0); result = 31 * result + (int) (expiryDate ^ (expiryDate >>> 32)); result = 31 * result + (int) (startDate ^ (startDate >>> 32)); result = 31 * result + maxNodes; result = 31 * result + version; return result; } public static final class Fields { public static final String STATUS = "status"; public static final String UID = "uid"; public static final String TYPE = "type"; public static final String SUBSCRIPTION_TYPE = "subscription_type"; public static final String ISSUE_DATE_IN_MILLIS = "issue_date_in_millis"; public static final String ISSUE_DATE = "issue_date"; public static final String FEATURE = "feature"; public static final String EXPIRY_DATE_IN_MILLIS = "expiry_date_in_millis"; public static final String EXPIRY_DATE = "expiry_date"; public static final String START_DATE_IN_MILLIS = "start_date_in_millis"; public static final String START_DATE = "start_date"; public static final String MAX_NODES = "max_nodes"; public static final String MAX_RESOURCE_UNITS = "max_resource_units"; public static final String ISSUED_TO = "issued_to"; public static final String ISSUER = "issuer"; public static final String VERSION = "version"; public static final String SIGNATURE = "signature"; public static final String LICENSES = "licenses"; public static final String LICENSE = "license"; } private static long parseDate(XContentParser parser, String description, boolean endOfTheDay) throws IOException { if (parser.currentToken() == XContentParser.Token.VALUE_NUMBER) { return parser.longValue(); } else { try { if (endOfTheDay) { return DateUtils.endOfTheDay(parser.text()); } else { return DateUtils.beginningOfTheDay(parser.text()); } } catch (IllegalArgumentException ex) { throw new ElasticsearchParseException("invalid " + description + " date format " + parser.text()); } } } public static Builder builder() { return new Builder(); } public static class Builder { private int version = License.VERSION_CURRENT; private String uid; private String issuer; private String issuedTo; private long issueDate = -1; private String type; private String subscriptionType; private String feature; private String signature; private long expiryDate = -1; private long startDate = -1; private int maxNodes = -1; private int maxResourceUnits = -1; public Builder uid(String uid) { this.uid = uid; return this; } public Builder version(int version) { this.version = version; return this; } public Builder issuer(String issuer) { this.issuer = issuer; return this; } public Builder issuedTo(String issuedTo) { this.issuedTo = issuedTo; return this; } public Builder issueDate(long issueDate) { this.issueDate = issueDate; return this; } public Builder type(LicenseType type) { return type(type.getTypeName()); } public Builder type(String type) { this.type = type; return this; } public Builder subscriptionType(String subscriptionType) { this.subscriptionType = subscriptionType; return this; } public Builder feature(String feature) { this.feature = feature; return this; } public Builder expiryDate(long expiryDate) { this.expiryDate = expiryDate; return this; } public Builder maxNodes(int maxNodes) { this.maxNodes = maxNodes; return this; } public Builder maxResourceUnits(int maxUnits) { this.maxResourceUnits = maxUnits; return this; } public Builder signature(String signature) { if (signature != null) { this.signature = signature; } return this; } public Builder startDate(long startDate) { this.startDate = startDate; return this; } public Builder fromLicenseSpec(License license, String licenseSignature) { return uid(license.uid()).version(license.version()) .issuedTo(license.issuedTo()) .issueDate(license.issueDate()) .startDate(license.startDate()) .type(license.type()) .subscriptionType(license.subscriptionType) .feature(license.feature) .maxNodes(license.maxNodes()) .maxResourceUnits(license.maxResourceUnits()) .expiryDate(license.expiryDate()) .issuer(license.issuer()) .signature(licenseSignature); } /** * Returns a builder that converts pre 2.0 licenses * to the new license format */ public Builder fromPre20LicenseSpec(License pre20License) { return uid(pre20License.uid()).issuedTo(pre20License.issuedTo()) .issueDate(pre20License.issueDate()) .maxNodes(pre20License.maxNodes()) .expiryDate(pre20License.expiryDate()); } public License build() { return new License( version, uid, issuer, issuedTo, issueDate, type, subscriptionType, feature, signature, expiryDate, maxNodes, maxResourceUnits, startDate ); } public Builder validate() { if (issuer == null) { throw new IllegalStateException("issuer can not be null"); } else if (issuedTo == null) { throw new IllegalStateException("issuedTo can not be null"); } else if (issueDate == -1) { throw new IllegalStateException("issueDate has to be set"); } else if (type == null) { throw new IllegalStateException("type can not be null"); } else if (uid == null) { throw new IllegalStateException("uid can not be null"); } else if (signature == null) { throw new IllegalStateException("signature can not be null"); } else if (expiryDate == -1) { throw new IllegalStateException("expiryDate has to be set"); } validateLimits(type, maxNodes, maxResourceUnits); return this; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy