Using the API

This page shows you how to use the Application Programming Interface of your project, or more specifically, its Key Generator and Key Manager modules. For documentation for the TrueLicense API, please refer to the TrueLicense Javadoc. Source code and Javadoc for the TrueLicense API are available on Maven Central for download.

Using the Key Generator API

Warning

The Key Generator module is used to generate license keys for your software product without requiring authorization. Therefore, you should keep this module under lock and key! In particular, do not distribute it to users or the public! The same concern applies to any derivative work which includes this module. This limits the set of valid use cases for using the Key Generator API. For example, you may want to develop a RESTful web service which generates license keys once users have paid for them.

Setting Up the Class Path

With Maven

Using Maven is the recommended way to integrate the project into your software product. Add the following dependency to the POM for your software product:

<dependency>
    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}-keygen</artifactId>
    <version>${version}</version>
</dependency>
Without Maven

Without Maven, you need to manually add the JARs of the project to the class path of your software product.

You can add the standalone JAR ${artifactId}-keygen/target/${artifactId}-keygen-${version}-standalone.JAR to the class path. This is convenient because the standalone JAR contains all transitive dependencies, so you only need to add this JAR to the class path.

If some of the dependencies bundled in the standalone JAR conflict with other dependencies of your software product however, then you may need to add only selected JARs to the class path. First, copy the runtime dependencies to the directory ${artifactId}-keygen/target/dependency using:

$ mvn package dependency:copy-dependencies -DincludeScope=runtime -pl *-keygen
[...]
$ ls *-keygen/target/dependency
annotations-3.0.0.jar                      jackson-module-jaxb-annotations-2.5.1.jar
commons-codec-1.10.jar                     truelicense-core-2.4-SNAPSHOT.jar
jackson-annotations-2.5.0.jar              truelicense-v2-json-2.4-SNAPSHOT.jar
jackson-core-2.5.1.jar                     truelicense-obfuscate-2.4-SNAPSHOT.jar
jackson-databind-2.5.1.jar

Now you can select each JAR you want to add to the class path from this directory. Don’t forget to add the regular JAR ${artifactId}-keygen/target/${artifactId}-keygen-${version}.jar to the class path, too.

Introduction to the API

When building your project, the following classes are generated from a set of Apache Velocity template files - listed in alphabetic order:

${package}.keygen.LicenseManager
The enumeration of the vendor license managers for your software product. The managers are named like each configured edition and ordered from superset to subset. Each manager is configured with the algorithms and parameters for generating license keys for the respective edition.
${package}.keygen.LicensingSchema
Deprecated - provided for compatibility only.
${package}.keygen.Main
The command line interface for vending license keys.

The main entry point to the API is the enumeration class LicenseManager. For example, if the project defines the property ${editions} to be enterprise standard, then this class is defined as follows:

package ${package}.keygen;

public enum LicenseManager implements VendorLicenseManager {

    enterprise { [...] },
    standard { [...] };

    [...]
}

For the following examples, it’s necessary to add the following imports:

import ${package}.keygen.*;
import net.truelicense.api.*;

Generating a License Key

You can generate a license key using:

VendorLicenseManager manager = LicenseManager.${edition};
LicenseVendorContext context = manager.context();
License bean = context.license();
Sink sink = context.pathStore(java.nio.file.Paths.get("${license-key-path}"));
manager.generate(bean, sink);

… where ${edition} references an edition of your software product, ${license-key-path} references the path of the license key file, manager is an instance of the class net.truelicense.api.VendorLicenseManager, context is an instance of the class [net.truelicense.api.LicenseVendorContext], bean is an instance of the class net.truelicense.api.License and sink is an instance of the class net.truelicense.api.io.Sink and

For a fully elaborated example, please have a look at the Main class.

Working with Runtime Exceptions

The VendorLicenseManager interface may generally throw a net.truelicense.api.LicenseManagementException, which is a GeneralSecurityException, which is a (checked) Exception. Working with checked exceptions may be cumbersome in contexts where a method is constrained to only throw unchecked exceptions, e.g. when implementing Runnable.run(). For these uses cases there exists an adapter method named net.truelicense.api.VendorLicenseManager.unchecked(): This method adapts a vendor license manager so that it may generally throw an net.truelicense.api.UncheckedLicenseManagementException, which is an (unchecked) RuntimeException and wraps the original LicenseManagementException. Here’s the general usage pattern:

VendorLicenseManager checkedManager = ...;
UncheckedVendorLicenseManager uncheckedManager = checkedManager.unchecked());
uncheckedManager.generateKeyFrom(someLicense).saveTo(someSink); // throws UncheckedLicenseManagementException

You can get back the original (checked) vendor license manager by calling:

UncheckedVendorLicenseManager uncheckedManager = ...;
VendorLicenseManager checkedManager = uncheckedManager.checked();

Using the Key Manager API

Setting Up the Class Path

With Maven

Using Maven is the recommended way to integrate the project into your software product. Add the following dependency to the POM for your software product:

<dependency>
    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}-keymgr</artifactId>
    <version>${version}</version>
</dependency>
Without Maven

Without Maven, you need to manually add the JARs of the project to the class path of your software product.

You can add the standalone JAR ${artifactId}-keymgr/target/${artifactId}-keymgr-${version}-standalone.JAR to the class path. This is convenient because the standalone JAR contains all transitive dependencies, so you only need to add this JAR to the class path.

If some of the dependencies bundled in the standalone JAR conflict with other dependencies of your software product however, then you may need to add only selected JARs to the class path. First, copy the runtime dependencies to the directory ${artifactId}-keymgr/target/dependency using:

$ mvn package dependency:copy-dependencies -DincludeScope=runtime -pl *-keymgr
[...]
$ ls *-keymgr/target/dependency
annotations-3.0.0.jar                      truelicense-core-2.4-SNAPSHOT.jar
commons-codec-1.10.jar                     truelicense-v2-json-2.4-SNAPSHOT.jar
jackson-annotations-2.5.0.jar              truelicense-obfuscate-2.4-SNAPSHOT.jar
jackson-core-2.5.1.jar                     truelicense-swing-2.4-SNAPSHOT.jar
jackson-databind-2.5.1.jar                 truelicense-ui-2.4-SNAPSHOT.jar
jackson-module-jaxb-annotations-2.5.1.jar

Now you can select each JAR you want to add to the class path from this directory. Don’t forget to add the regular JAR ${artifactId}-keymgr/target/${artifactId}-keymgr-${version}.jar to the class path, too.

Introduction to the API

When building your project, the following classes are generated from a set of Apache Velocity template files - listed in alphabetic order:

${package}.keymgr.LicenseManager
The enumeration of the consumer license managers for your software product. The managers are named like each configured edition and ordered from superset to subset, including an optional FTP. Each manager is configured with the algorithms and parameters for installing, loading, verifying and uninstalling license keys for the respective edition.
${package}.keymgr.LicensingSchema
Deprecated - provided for compatibility only.
${package}.keymgr.Main
The command line interface for consuming license keys.

The main entry point to the API is the enumeration class LicenseManager. For example, if the project defines the properties ${editions} to be enterprise standard and ${freeTrialPeriod} to be 30, then this class is defined as follows:

package ${package}.keymgr;

public enum LicenseManager implements ConsumerLicenseManager {

    enterprise { [...] },
    standard { [...] },
    ftp { [...] };

    public static LicenseManager get() { return ftp; }

    [...]
}

Consumer license managers are arranged in a chain of responsibility, ordered from feature subset to feature superset (which is the reverse order of the items in the enumeration class LicenseManager). When installing, loading, verifying or uninstalling a license key, each operation is tried using the parent manager first. If the operation succeeds using the parent manager then the processing stops, otherwise the operation is retried using the child manager. This repeats recursively until the operation either succeeds using some manager or no more managers are available, in which case a net.truelicense.api.LicenseManagementException is thrown.

This design allows you to use the API for installing, loading, verifying and uninstalling license keys without knowing for which edition a license key has been generated. To facilitate this, the LicenseManager class provides the get() method which returns the first manager in the configured chain-of-responsibility.

For the following examples, it’s necessary to add the following imports:

import ${package}.keymgr.*;
import net.truelicense.api.*;

Installing a License Key

You can install a license key using:

ConsumerLicenseManager manager = LicenseManager.get();
LicenseManagementContext context = manager.context();
Source source = context.pathStore(java.nio.file.Paths.get("${license-key-path}"));
manager.install(source);

… where ${license-key-path} references the path of the license key file, manager is an instance of the class net.truelicense.api.ConsumerLicenseManager, context is an instance of the class net.truelicense.api.LicenseManagementContext and source is an instance of the class net.truelicense.api.io.Source

According to the chain-of-responsibility pattern, LicenseManager.install(Source) recursively tries each consumer license manager until the given license key fits the respective lock and saves it. It’s not necessary to know for which edition the license key has been generated.

If the given file does not hold a license key for the lock of any license consumer manager, then a net.truelicense.api.LicenseManagementException is thrown instead.

Loading the License Key

You can load the installed license key using:

License bean = LicenseManager.get().load();

… where bean is an instance of the class net.truelicense.api.License.

According to the chain-of-responsibility pattern, LicenseManager.load() recursively tries each consumer license manager until an installed license key is found and returns a duplicate of its encoded license bean. It’s not necessary to know for which edition the installed license key has been generated. Note that this method does not validate the encoded license bean, so for example, it’s term may have already expired.

If no license key is installed, then a net.truelicense.api.LicenseManagementException is thrown instead.

Verifying the License Key

You can verify the installed license key using:

LicenseManager.get().verify();

According to the chain-of-responsibility pattern, LicenseManager.verify() recursively tries each consumer license manager until an installed license key is found which passes validation, too.

If no license key is installed, then a net.truelicense.api.LicenseManagementException is thrown instead.

If a license key is installed, but the encoded license bean is invalid, then a net.truelicense.api.LicenseValidationException is thrown instead.

You need to call this method in advance whenever you want to access a feature of your software product. Calling this method frequently ensures that your software product detects any license term expiration as soon as possible.

You don’t need to worry about performance: TrueLicense maintains a time sensitive cache in order to speed up subsequent processing. For example, on an Intel i7 at 2.2 GHz, once a valid V2/JSON license key is installed you can get about 9.5 million successful license key verifications in a single thread! Of course, this depends not only on the hardware, but also on the configuration of the licensing schema, so your mileage may vary.

Supporting Multiple Editions

The use case for verifying a license key is different from the use case for the other operations: When installing, loading or uninstalling a license key, it’s not relevant for which edition a license key has been generated. The chain-of-responsibility pattern then ensures that these operations will succeed when calling them on LicenseManager.get(), which is the first manager in the chain.

However, when verifying access to a feature, then you want to make sure that access is granted if and only if a valid license key is installed for the respective edition or any of its supersets, but not its subsets. To do this, you need to directly use the instances of the enumeration class LicenseManager.

For example, assuming the same definition of this class, the following code accepts a valid license key for the enterprise edition only:

LicenseManager.enterprise.verify();

Likewise, the following code accepts a valid license key for the enterprise edition or the standard edition:

LicenseManager.standard.verify();

Likewise, the following code accepts a valid license key for the enterprise edition or the standard edition or the FTP edition:

LicenseManager.ftp.verify();

Note that modelling the FTP as an edition allows you to limit access to some features to registered customers only. Employing this option is trivial: Just call the verify() method on any license manager other than LicenseManager.ftp.

Uninstalling the License Key

You can uninstall the license key using:

LicenseManager.get().uninstall();

According to the chain-of-responsibility pattern, LicenseManager.uninstall() recursively tries each consumer license manager until an installed license key is found and deletes it. It’s not necessary to know for which edition the installed license key has been generated.

If no license key is installed or only an auto-generated FTP license key is installed, then a net.truelicense.api.LicenseManagementException is thrown instead.

Working with Runtime Exceptions

The ConsumerLicenseManager interface may generally throw a net.truelicense.api.LicenseManagementException, which is a GeneralSecurityException, which is a (checked) Exception. Working with checked exceptions may be cumbersome in contexts where a method is constrained to only throw unchecked exceptions, e.g. when implementing Runnable.run(). For these uses cases there exists an adapter method named net.truelicense.api.ConsumerLicenseManager.unchecked(): This method adapts a consumer license manager so that it may generally throw an net.truelicense.api.UncheckedLicenseManagementException, which is an (unchecked) RuntimeException and wraps the original LicenseManagementException. Here’s the general usage pattern:

ConsumerLicenseManager checkedManager = ...;
UncheckedConsumerLicenseManager uncheckedManager = checkedManager.unchecked());
uncheckedManager.install(someSource); // throws UncheckedLicenseManagementException

You can get back the original (checked) consumer license manager by calling:

UncheckedConsumerLicenseManager uncheckedManager = ...;
ConsumerLicenseManager checkedManager = uncheckedManager.checked();