Shelf Life
PreEmptive Protection™ DashO™ for Android & Java can inject Shelf Life into applications. Shelf Life is an application inventory management function that allows you to add expiration and notification logic to your application. This logic enforces an expiration policy by exiting the application. For example, a beta application can be made to expire on a particular date. You can schedule an application's expiration for a specific date or a number of days from a starting date and optionally specify a warning period prior to expiration. The expiration information may be placed within your application or can be read from an encrypted external token file. The latter allows you to extend the expiration of the application by issuing a new token file rather than rebuilding your application. Shelf Life Checks can be added to one or more locations in your application.
Activation Key
To start using Shelf Life you must obtain a Shelf Life Activation Key from PreEmptive. This key is used to generate the tokens that contain the expiration information. PreEmptive will issue you a data file containing the key that generates the tokens and identifies your application. This key is read by DashO either when the code has checks injected, or or when tokens are generated if managed externally from the compiled binary. The location of the key file can be specified in the user interface or in the project configuration file.
Shelf Life Tokens
A Shelf Life Token is an encrypted set of data containing application and expiration information.
It can be inserted into your application or stored outside of the application.
You can use the DashO user interface, the tokengenerator
command line utility, or an Ant task to create an externally stored token.
The expiration and warning information for the token is entered via the user interface or via Shelf Life annotations, which can be added to your source code. Expiration and warning dates can be specified in two different ways:
Absolute Dates – A fixed date for the expiration date or the beginning of the warning period can be specified.
Relative Dates – The expiration period is the number of days from a start date. The warning period is the number of days prior to the expiration date.
You can combine absolute and relative dates - e.g. expire on 1/1/2021 and warn 30 days before expiration. Expiration information is required to create the token, but warning information is optional.
Shelf Life Check
The ShelfLifeCheck annotation is used to define the location in your application where a Shelf Life Check will take place.
The @ShelfLifeCheck
annotation can be added to your sources, or a ShelfLifeCheck can be added from the Checks – Shelf Life screen.
If the expiration information is set on the Checks – Shelf Life screen, at the minimum a key file and expiration date, only a single annotation is required to add the Shelf Life Check:
@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]);
}
}
This adds a Shelf Life Check to the application at the start of main()
.
You can also specify all the information as annotation attributes:
@ShelfLifeCheck(expirationDate = "01/01/2021", warningPeriod = "30")
public static void main(final String[] args){
// ...
}
The values for the attributes, dates, periods, and field/method references, are all strings. This allows you to use DashO's properties or environment values to parameterize them:
@ShelfLifeCheck(expirationDate = "01/01/${exp_year}", warningPeriod = "${warn_period}")
public static void main(final String[] args){
// ...
}
Relative Expiration Date
Expiration can be specified as a number of days from a dynamic start date. The start date could be something like the install date or the date on which the application is first run. The start date is provided at runtime by your application:
@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));
}
You can use static or instance methods or fields as a source for the start date. See Specifying Sources and Actions for details.
Externally Stored Tokens
In the previous example DashO has embedded the Shelf Life token into the application. The token can also be stored and managed externally as a file or resource and read in at runtime:
@ShelfLifeCheck(tokenSource = "@getToken()")
public static void main(final String[] args){
// ...
}
private static Reader getToken(){
return new InputStreamReader(HelloWorld.class.getClassLoader().
getResourceAsStream("expiry.dat"));
}
The source for the token is a field of type or a zero-argument method returning a java.io.Reader
that provides the token data (as read from a file, for example).
See Specifying Sources and Actions for details.
Shelf Life Action
When ShelfLifeCheck
is executed, if the application has expired, the default action is to print a message to System.out
(or a dialog) and exit with a return code of 1
:
This application expired on January 1, 2017
If the application is in the warning period a message is printed to System.out
(or a dialog) and execution continues:
This application will expire on December 31, 2017
Note: On Android, the default expiration action taken will close the
Activity
where the Check was injected. If it was not injected into anActivity
, it will throw aRuntimeException
.
For a more sophisticated application a custom application action can be specified:
@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 action is passed the Shelf Life token that is then used to determine the action to be taken.
Token Class Reference
Shelf life tokens are represented by the com.preemptive.instrumentation.Token
class, packaged in shelflife-java.jar
and shelflife-android.jar
.
This class provides information about the token's expiration and warning dates, and also can provide access to properties that have been added to the token.
Note:
Shelf Life runtime classes are automatically merged into your project's output if Shelf Life Checks are injected. You do not need to includeshelflife-java.jar
orshelflife-android.jar
as an input or a support for your project.
Methods
hasWarningDate()
public boolean hasWarningDate()
Does the token have a warning date set?
Returns:
true
if the token has a warning date set.
getWarningDate()
public java.util.Date getWarningDate()
Get the warning date stored in the token.
Returns:
The warning date, or null
if none has been set.
getExpirationDate()
public java.util.Date getExpirationDate()
Get the expiration date stored in the token.
Returns:
The expiration date.
isInWarning()
public boolean isInWarning()
Is the current time after the warning date?
Returns:
true
if the current time is after the warning date.
If the token does not contain a warning date, then false
is returned.
isExpired()
public boolean isExpired()
Has the token expired?
Returns:
true
if the token has an expiration data set and the current time is after the expiration date.
getID()
public java.lang.String getID()
Get the Shelf Life ID used to create the token.
Returns:
The Shelf Life ID used to create the token.
getDaysTillExpiration()
public int getDaysTillExpiration()
Get the number of days until the expiration date will be reached.
Returns:
The number of days before the expiration date will be reached.
getProperties()
public java.util.Properties getProperties()
Get the properties stored in the token.
Returns:
The properties stored in the token.
getToken(File)
public static Token getToken(java.io.File file)
Read a token that has been stored in a file. This cannot be used with token that contain relative dates, use getToken(Date, File).
Parameters:
file
- the file that contains the token encoded as a base64 string.
Returns:
The token, or null
if token cannot be read from the file.
getToken(Date, File)
public static Token getToken(java.util.Date startDate,
java.io.File file)
Read a token that uses a relative dates from a file.
Parameters:
startDate
- the starting data for the relative dates.
file
- the file that contains the token encoded as a base64 string.
Returns:
The token or null if token cannot be read from the file.
See Also:
getToken(Reader)
public static Token getToken(java.io.Reader reader)
Read a token. This cannot be used with token that contain relative dates, use getToken(Date, Reader).
Parameters:
reader
- contains the token encoded as a base64 string.
This is closed at the end of this method.
Returns:
The extracted token, or null
on any error.
getToken(Date, Reader)
public static Token getToken(java.util.Date startDate,
java.io.Reader reader)
Read a token.
Parameters:
reader
- contains the token encoded as a base64 string.
This is closed at the end of this method.
Returns:
The extracted token, or null
on any error.
See Also:
getToken(String)
public static Token getToken(java.lang.String encoded)
Read a token stored in a string. This cannot be used with token that contain relative dates, use getToken(Date, String).
Parameters:
encoded
- a token encoded as a base64 string.
Returns:
The extracted token or null on any error.
getToken(Date, String)
public static Token getToken(java.util.Date startDate,
java.lang.String encoded)
Read a token stored in a string.
Parameters:
encoded
- a token encoded as a base64 string
Returns:
The extracted token, or null
on any error.
See Also: