Shelf Life adds expiration and optional warning logic to an application. Use it to limit a beta, trial, preview, or other time-bound build to an absolute date or to a specified number of days from a runtime start date.
DashO can embed the encrypted expiration token in the protected application, or the application can load it from an external file or resource. With an external token, you can extend the expiration period without rebuilding and redistributing the application.
Before you begin
- Obtain a Shelf Life activation-key file from PreEmptive. The file authorizes token creation and identifies the application.
- Store the activation-key file securely.
- Configure the key-file location in the DashO user interface or project configuration.
- Decide whether to embed the token in the application or manage it externally.
- Decide whether to use an absolute expiration date or a relative expiration period.
- Decide whether to use the default expiration behavior or implement a custom action.
Choose a token storage model
| Model | How it works | Use when |
| Embedded token | DashO inserts the expiration data into the protected application. | You want a simple deployment and can rebuild and redistribute the application when the expiration changes. |
| External token | The application reads an encrypted token from a file, resource, property, or another Reader source. |
You want to extend the expiration period by issuing a new token without rebuilding the application. |
Choose expiration and warning values
Shelf Life supports the following expiration models:
- Absolute date: Set a fixed expiration date or warning start date.
- Relative period: Set the number of days from a start date supplied by the application. You can also set the warning period as the number of days before expiration.
Expiration information is required. Warning information is optional.
You can combine absolute and relative values. For example, you can use a fixed expiration date and start displaying warnings 30 days before that date.
Configure a Shelf Life check in DashO
- Open Checks > Shelf Life.
- Select the Shelf Life activation-key file.
- Configure an absolute expiration date or a relative expiration period.
- For a relative expiration period, configure the source that provides the runtime start date.
- Optionally configure an absolute warning date or warning period.
- For an external token, configure a token source that returns
java.io.Reader. - Optionally add custom properties to the token.
- Optionally configure a custom action that receives the
Tokenobject. - Add one or more injection locations.
- Build the protected application.
For more information about the available DashO settings, see Configure Runtime Protection Checks in DashO.
Configure an embedded token with annotations
When you configure the activation key and expiration defaults in DashO, add ShelfLifeCheck to each required injection location:
@ShelfLifeCheck
public static void main(final String[] args){
if(args.length == 0){
System.out.println("Hello no name");
} else {
System.out.println("Hello " + args[0]);
}
}You can also define expiration and warning values directly in the annotation:
@ShelfLifeCheck(expirationDate = "01/01/2021", warningPeriod = "30")
public static void main(final String[] args){
// ...
}The annotation attributes—including dates, periods, and field or method references—are strings. Therefore, you can use DashO properties or environment values to parameterize them:
@ShelfLifeCheck(expirationDate = "01/01/${exp_year}", warningPeriod = "${warn_period}")
public static void main(final String[] args){
// ...
}Configure a relative expiration period
Use startDateSource to specify a compatible field or method that supplies the runtime start date.
The field must be of type java.util.Date, or the method must accept no arguments and return java.util.Date.
@ShelfLifeCheck(startDateSource = "@getInstallDate()", expirationPeriod = "90")
public static void main(final String[] args){
// ...
}
private static Date getInstallDate(){
return new Date(Preferences.userRoot().node("MyApp").getInt("installDate", 0));
}This example assumes the application has already stored installDate as the number of milliseconds since the Unix epoch.
Use Preferences.getLong() rather than Preferences.getInt() because an epoch timestamp exceeds the range supported by an int.
Load an external token
Use tokenSource to identify a field of type Reader or a zero-argument method that returns Reader:
@ShelfLifeCheck(tokenSource = "@getToken()")
public static void main(final String[] args){
// ...
}
private static Reader getToken(){
return new InputStreamReader(HelloWorld.class.getClassLoader().
getResourceAsStream("expiry.dat"));
}The Reader supplies the encrypted token data from a file, resource, property, or another external source. DashO closes the Reader automatically after reading the token.
If the external token uses a relative expiration period, you must also provide a runtime start date.
For information about creating external tokens, see Generate Shelf Life Tokens.
Control expiration behavior
When you do not configure a custom action, Shelf Life uses its default expiration behavior:
- If the application is in its warning period, Shelf Life displays or prints a warning and allows execution to continue.
- If a Java application has expired, Shelf Life displays or prints an expiration message and exits with return code
1.
Android behavior: The default expiration action closes the Activity containing the check. If the check is not injected into an Activity, DashO throws a RuntimeException.
To implement custom behavior, configure an action method that accepts a com.preemptive.instrumentation.Token object and returns void:
@ShelfLifeCheck(action = "@check()")
public static void main(final String[] args){
// ...
}
private static void check(Token token) {
if(token.isExpired()){
JOptionPane.showMessageDialog(null,
"The application expired on " + token.getExpirationDate(),
"Expired",
JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
if(token.isInWarning()){
JOptionPane.showMessageDialog(null,
"The application will expire in " +
token.getDaysTillExpiration() + " days",
"Expiration Warning",
JOptionPane.WARNING_MESSAGE);
}
}The custom action is called whenever the Shelf Life check runs. The action can inspect the supplied token to determine whether the application is expired, in its warning period, or still valid.
Token class methods
Shelf Life tokens are represented by the com.preemptive.instrumentation.Token class.
The class is packaged in shelflife-java.jar and shelflife-android.jar. When DashO injects Shelf Life checks, the required runtime classes are automatically merged into the protected application. You do not need to add these JAR files as application inputs or support libraries.
For complete signatures, parameter descriptions, return values, and usage details, see Shelf Life Token Reference.
Android Context requirement
A Shelf Life check on Android requires access to the application context. The injection class must provide a getApplicationContext() method.
Activities, application classes, services, and other subclasses of android.content.Context inherit this method and do not require additional changes.
If the injection class does not provide getApplicationContext(), add a method that returns the correct Android Context.