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

net.java.truelicense.core.License Maven / Gradle / Ivy

Go to download

The TrueLicense Core module provides essential functionality for license management.

There is a newer version: 2.6.6
Show newest version
/*
 * Copyright (C) 2005-2013 Schlichtherle IT Services.
 * All rights reserved. Use is subject to license terms.
 */
package net.java.truelicense.core;

import java.beans.*;
import java.util.*;
import static java.util.Calendar.*;
import javax.annotation.*;
import javax.security.auth.x500.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.java.truelicense.core.codec.*;
import net.java.truelicense.core.util.Objects;

/**
 * A Java Bean which defines and provides the common properties of any license.
 * In general, all properties may be {@code null} to indicate that this
 * property is not set.
 * However, {@linkplain LicenseValidation#validate license validation} may fail
 * if some properties are not set when
 * {@linkplain LicenseVendorManager#create creating},
 * {@linkplain LicenseConsumerManager#install installing} or
 * {@linkplain LicenseConsumerManager#verify verifying}
 * license keys.
 * 

* There are two options for extending a license with custom properties: *

    *
  • The easiest way is to wrap the custom properties in another Java Bean * and store it in the {@linkplain #setExtra(Object) extra} property * (composition). *
  • Another option is to subclass this class and add the custom properties * (inheritance). * However, you may then need to override {@link #equals(Object)}, too. * If you do, you also need to override {@link #hashCode()} for consistency. *
* Either way, the custom properties must support the {@link Codec} of the * respective license key format - see {@link LicenseManagementContext#codec}. * This is easiest to achieve if the respective class follows the JavaBean * pattern just like this class does. *

* Note that this class deviates from the JavaBeans specification in that it * neither implements {@link java.io.Serializable} nor * {@link java.io.Externalizable}. * This is because serialization is not required with the used {@code Codec}s * and creates a major obligation for any subclass. * * @see LicenseProvider * @author Christian Schlichtherle */ // #TRUELICENSE-50: The XML element name MUST be explicitly defined! // Otherwise, it would get derived from the class name, but this would break // if the class name gets obfuscated, e.g. when using the ProGuard // configuration from the TrueLicense Maven Archetype. @XmlRootElement(name = "license") @Nullable public class License { private int consumerAmount = 1; private String consumerType; private Object extra; private X500Principal holder; private String info; private Date issued; private X500Principal issuer; private Date notAfter; private Date notBefore; private String subject; /** * Returns the amount of consumers which are allowed to use the licensing * subject. * The default value is one in order to retain interoperability with V1 * format license keys and to reduce the size of the XML encoded form * (default values don't need to get encoded). */ @XmlElement(defaultValue = "1") public final int getConsumerAmount() { return consumerAmount; } /** * Sets the amount of consumers which are allowed to use the licensing * subject. */ public final void setConsumerAmount(final int consumerAmount) { this.consumerAmount = consumerAmount; } /** * Returns the description of the type of the entity or object which * allocates (consumes) the license for using the licensing subject. * This could describe a computer or a user or anything else, e.g. * {@code "User"}. */ @XmlElement(required = true) public final String getConsumerType() { return consumerType; } /** * Sets the description of the type of the entity or object which * allocates (consumes) the license for using the licensing subject. */ public final void setConsumerType(final String consumerType) { this.consumerType = consumerType; } /** * Returns the private license extra data. * This may be any object which supports serialization via * {@link XMLEncoder}. * It is typically used by applications to provide some extra data for * custom validation. */ public final Object getExtra() { return extra; } /** * Sets the private license extra data. * * @param extra the private license extra data. * This object must support serialization via {@link XMLEncoder}. */ public final void setExtra(final Object extra) { this.extra = extra; } /** * Returns the description of the legal entity to which the license is * granted by the issuer/vendor. * This could describe a person or an organization or be a placeholder for * any of these, e.g. {@code new X500Principal("CN=Anonymous")}. */ @XmlElement(required = true) @XmlJavaTypeAdapter(X500PrincipalXmlAdapter.class) public final X500Principal getHolder() { return holder; } /** * Sets the description of the legal entity to which the license is * granted by the issuer/vendor. */ public final void setHolder(final X500Principal holder) { this.holder = holder; } /** * Returns the license information. * This could be any text which may be displayed to users for informational * purposes, e.g. in a GUI dialog. */ public final String getInfo() { return info; } /** * Sets the license information. */ public final void setInfo(final String info) { this.info = info; } /** * Returns the date/time when the license has been issued. * Note that a protective copy is made. */ @XmlElement(required = true) public final Date getIssued() { return clone(issued); } /** * Sets the date/time when the license has been issued. * Note that a protective copy is made. */ public final void setIssued(final Date issued) { this.issued = clone(issued); } /** * Returns the description of the legal entity which grants the license to * the holder/consumer. * This could describe a person or an organization or be a placeholder for * any of these, but typically describes an organization e.g. * {@code new X500Principal("CN=Christian Schlichtherle,O=Schlichtherle IT Services")}. */ @XmlElement(required = true) @XmlJavaTypeAdapter(X500PrincipalXmlAdapter.class) public final X500Principal getIssuer() { return issuer; } /** * Sets the description of the legal entity which grants the license to * the holder/consumer. */ public final void setIssuer(final X500Principal issuer) { this.issuer = issuer; } /** * Returns the date/time when the license ends to be valid (expires). * Note that a protective copy is made. */ public final Date getNotAfter() { return clone(notAfter); } /** * Sets the date/time when the license ends to be valid (expires). * Note that a protective copy is made. */ public final void setNotAfter(final Date notAfter) { this.notAfter = clone(notAfter); } /** * Returns the date/time when the license begins to be valid. * Note that a protective copy is made. */ public final Date getNotBefore() { return clone(notBefore); } /** * Sets the date/time when the license begins to be valid. * Note that a protective copy is made. */ public final void setNotBefore(final Date notBefore) { this.notBefore = clone(notBefore); } /** * Conveniently computes the {@code issued} date/time, {@code notBefore} * date/time and {@code notAfter} date/time properties from the given * number of days. *

* Note that this computation depends on the system clock unless the * property {@code issued} is set. * However, this is not a security issue because this method is neither * used for license initialization nor validation by a license consumer * manager. * * @param days the validity period in (24 hour) days from now. */ public final void setTerm(final int days) { Date issued = getIssued(); if (null == issued) { issued = new Date(); setIssued(issued); } setNotBefore(issued); final Calendar cal = getInstance(); cal.setTime(issued); cal.add(DATE, days); setNotAfter(cal.getTime()); } /** * Returns the description of the product which requires licensing. * This could be any string, but is recommended to contain the canonical * name of the application and some information for which version number * range this license is applicable, e.g. {@code "MyApp 1.X"}. */ @XmlElement(required = true) public final String getSubject() { return subject; } /** Sets the description of the product which requires licensing. */ public final void setSubject(final String subject) { this.subject = subject; } private static Date clone(Date date) { return null == date ? null : (Date) date.clone(); } /** * Returns {@code true} if and only if {@code obj} is an instance of the * {@link License class} and its properties compare * {@linkplain Object#equals(Object) equal} to the properties of this * license. */ @Override @SuppressWarnings("AccessingNonPublicFieldOfAnotherObject") public boolean equals(final Object obj) { if (this == obj) return true; if (!(obj instanceof License)) return false; final License that = (License) obj; return this.consumerAmount == that.consumerAmount && Objects.equals(this.consumerType, that.consumerType) && Objects.equals(this.extra, that.extra) && Objects.equals(this.holder, that.holder) && Objects.equals(this.info, that.info) && Objects.equals(this.issued, that.issued) && Objects.equals(this.issuer, that.issuer) && Objects.equals(this.notAfter, that.notAfter) && Objects.equals(this.notBefore, that.notBefore) && Objects.equals(this.subject, that.subject); } /** Returns a hash code which is consistent with {@link #equals(Object)}. */ @Override public int hashCode() { int c = 17; c = 31 * c + consumerAmount; c = 31 * c + Objects.hashCode(consumerType); c = 31 * c + Objects.hashCode(extra); c = 31 * c + Objects.hashCode(holder); c = 31 * c + Objects.hashCode(info); c = 31 * c + Objects.hashCode(issued); c = 31 * c + Objects.hashCode(issuer); c = 31 * c + Objects.hashCode(notAfter); c = 31 * c + Objects.hashCode(notBefore); c = 31 * c + Objects.hashCode(subject); return c; } /** * Returns a string representation of this object for logging and debugging * purposes. */ @Override public String toString() { return String.format("%s@%x[subject=%s, holder=%s, issuer=%s, issued=%tc, notBefore=%tc, notAfter=%tc, consumerType=%s, consumerAmount=%d, info=%s]", getClass().getName(), hashCode(), literal(getSubject()), literal(getHolder()), literal(getIssuer()), getIssued(), getNotBefore(), getNotAfter(), literal(getConsumerType()), getConsumerAmount(), literal(getInfo())); } private static @Nullable String literal(final @CheckForNull Object obj) { if (null == obj) return null; final String s = obj.toString(); return '"' + s .replace("\\", "\\\\") .replace("\"", "\\\"") + '"'; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy