diff --git a/README b/README
deleted file mode 100644
index bc20128cc7beb3b0a9c090f8a0d251926ed68284..0000000000000000000000000000000000000000
--- a/README
+++ /dev/null
@@ -1,27 +0,0 @@
-# How it work ?
-
-
-# Usage
-
-## Generate your public and private key
-
-Create the private key (containing information to create the public key).
-
- $ openssl genrsa -out privkey.pem 2048
- $ openssl pkcs8 -topk8 -in privkey.pem -inform PEM -nocrypt -outform DER -out privkey.der
-
-Extract the public key, for publishing.
- $ openssl rsa -in privkey.pem -out pubkey.der -pubout -outform DER
-
-
-
-# License
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of Apache License 2.0
-
-You should have received a copy of the Apache License 2.0
-along with this program in the file named "LICENSE".
-
-This package is based on the following article:
-http://blog.afewguyscoding.com/2012/02/licensing-module-java/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..89503ea3f82055f8e49716721220f03dbda502b0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,74 @@
+# How it work ?
+This project provide a java library to be used by your java project to easily validate a license file.
+
+1. You generate a private and public key.
+2. You publish your application with this library and your public key.
+3. You keep the private key for youself.
+
+1. You generate a license file for your user with a deadline.
+2. You are sending this file to your user (via email or similar).
+3. Your user install this license file where your application can pick it up.
+4. When your application start, this library is used to validate the license file and validate the deadline.
+
+# Usage
+
+## Generate your public and private key
+
+Create the private key:
+
+ openssl genrsa -out privkey.pem 2048
+ openssl pkcs8 -topk8 -in privkey.pem -inform PEM -nocrypt -outform DER -out privkey.der
+
+Extract the public key, for publishing:
+
+ openssl rsa -in privkey.pem -out pubkey.der -pubout -outform DER
+
+## Publish your application with this library
+To make use of this license library, you must change a bit the implementation of your application. First, you must import the library. For maven project, you may edit the `pom.xml` as follow:
+
+
+
+ patrikdufresne
+ http://nexus.patrikdufresne.com/content/groups/public/
+
+
+
+ ...
+
+
+
+ com.patrikdufresne
+ license
+ 0.11
+
+
+
+
+In your java code, you must implement something similar.
+
+ License l;
+ try {
+ l = LicenseManager.validate(Main.class.getResourceAsStream("/pubkey.der"), new File("application.lic"));
+ } catch (LicenseException e) {
+ System.out.println("invalid license file:" + e.getMessage());
+ System.exit(1);
+ return;
+ }
+ System.out.println("License to: " + l.getProperty(License.NAME));
+ System.out.println("Expired: " + l.getProperty(License.EXPIRATION));
+
+Take a loot at http://git.patrikdufresne.com/pdsl/license/blob/master/docs/examples/Main.java
+
+## Generate a license file
+
+To generate a license file you may use the jar it self in command line:
+
+ wget https://nexus.patrikdufresne.com/repository/public/com/patrikdufresne/license/0.11/license-0.11.jar
+ java -jar license-0.11.jar create -p pubkey.der -P privkey.der -n username -m test@example.com -e 2020-01-09
+
+It's generate a license file named `application.lic`.
+
+
+# Notes
+This library is compatible with Java 7 and earlier. This library doesn't need any dependecies.
+
diff --git a/docs/examples/Main.java b/docs/examples/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5ef3e02edae627b2e23f184f96de7f2bde06f05
--- /dev/null
+++ b/docs/examples/Main.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright(C) 2013 Patrik Dufresne Service Logiciel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.ekwos;
+
+import java.io.File;
+
+import com.patrikdufresne.license.License;
+import com.patrikdufresne.license.LicenseException;
+import com.patrikdufresne.license.LicenseManager;
+
+public class Main {
+
+ public static void main(String[] args) {
+
+ License l;
+ try {
+ l = LicenseManager.validate(Main.class.getResourceAsStream("/pubkey.der"), new File("application.lic"));
+ } catch (LicenseException e) {
+ System.out.println("invalid license file:" + e.getMessage());
+ System.exit(1);
+ return;
+ }
+ System.out.println("License to: " + l.getProperty(License.NAME));
+ System.out.println("Expired: " + l.getProperty(License.EXPIRATION));
+
+ }
+
+}
diff --git a/docs/examples/application.lic b/docs/examples/application.lic
new file mode 100644
index 0000000000000000000000000000000000000000..a92afc7002dff6dec8d1e044bbf65cf31424ed6d
--- /dev/null
+++ b/docs/examples/application.lic
@@ -0,0 +1,7 @@
+#License file
+#Wed Jan 16 16:00:25 EST 2019
+signature=JLGa91NTwe4KBppK+dmy7JIor9QdW+frG8Zmun5i57b3b1jgeeNDtGibxM1poMdPPg4lyoP6R8qCQwSbfzE/DV7uj+awNzHesAxMohOfGI7rc7RH91o9OUzx8r1iuObJnOhhDOnxVmFrBdKxxYXopl1gqdF9B+wGzv7pyHp9hG3ayTId0NG6zISlX1RWDVqeVnXQoarVSa6Xmc7fBSW1XswFtyLCuJO932IS73V6Det0Y+3xAwvZRShouMSL5NOUyCZcwVCsvghY24x5BJYd7PmYOTEwuwW1uCEzRAu64G0a/Ysh/5/ciVc2FyNPOmODvf4P02FW6z6hL4sEfLcwyQ\=\=
+licenseType=trial
+expiration=2020-01-01
+email=info@patrikdufresne.com
+name=patrik
diff --git a/docs/examples/privkey.der b/docs/examples/privkey.der
new file mode 100644
index 0000000000000000000000000000000000000000..e2783a2d8d375804835860b3c91be1fad5479558
Binary files /dev/null and b/docs/examples/privkey.der differ
diff --git a/docs/examples/privkey.pem b/docs/examples/privkey.pem
new file mode 100644
index 0000000000000000000000000000000000000000..2de9fb3aba6b8acd5606611058c357c004b23014
--- /dev/null
+++ b/docs/examples/privkey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA2aUh7+dLXmrQqtTXOdZu9MktrAlG9x1Oo2xEVXD9lEuEGnP6
+VGCuE9Kib+945b8lSBgKgCrT0R3wajUDLH/3YzoX6O0B5kRrp7DlaCH6mUTmfpTv
+XvIfhIXamozfLRG6Rg0gGL7JMwspJYnct1dB4H9piCEM2jE2pDpLOUKEgvCz3yPW
+IF8aolLXs+P+0Ael3gpqGfIRtuHbTd8PTcTfEHhWc55D50qdptv2y624kKxU9mqY
+FHhTFBRbuFPKF80xAXzSmNhx+MIRzLZfhCxIj1HN7cJcQDCdDuisKJmn/nLWTsXd
+vmvM8FP8x8DKehukwibvx2AKb7xrE119+uU8JQIDAQABAoIBAAOR7NuVjKvwzplu
+wlUFim5jemdPA6X8ChUuKnTIVLCBCJqyelG2AET8+IMjh3UlTIRBOLLfgPf2KMJl
+OjcZpkIvasL8WEKhrq5ifXDW1dh7w9ghs0d4a0HuPCa61tJTbx3FC1i8kGpQ7Yzb
+FQ7A1KjNDjsYZ7CQjBfniOJYj/nh1yLycoPjNFjIp6kGn5t1yTk48iv5JPzJe/lE
+kZVC6BVt4oUc4W2bFsVxg0jXqFvM+nazbUFGFDV/rr3YxNILdBxCPVF5JtUyaqBj
+RMWgaWVEzgJjT9eKZwAE13SFufnyiI1UZquwi+2QQqdEbrB9cmq81GTnMURKj57g
+YVJ5GcECgYEA7rfH/KZ5iMFePYaH/g7Q7T7YemAzRDsQQ/hW7bd1I7YWmNqXOeJJ
+fycgTJaXJqD3X7658pHjp1gpUfemkBXIMIO4bcGgS3P10r0L890PGR6ZqdIYVoHn
+UuPc56junMO1/Ansz3HpUOlZV0iAdHgJ4YQvnT3SoaE56ndUSjUBNJECgYEA6WbN
+kfReAzxmkLpFOppNqG0lOJ2Rzbz05IzjnL7qrbL6KXm8X2VT5uK7QN13ceqgLUG3
+zRzQziBwVsim4EYP612I9bKsDTFjvsAm7fCnxvkgJEzh7jPeeXUlIrcchIUna5EQ
+TdxLU8FlwfK6gwjxZdjvq6pGpDnzo7/+rUJWSFUCgYEA44rwqMXyUMWo09KZbDSp
+N4tRA40RMPdvsKpWCe92S9z0Oy0ZOwaUcgxUgEyGtT53rZ76Vdpz+n5RnJ0H+o2Y
+rY3QzWXkKifVaNPkQcYz7wi5BiOKKWNXoS4r0fG3yFvQ6vZ28OGuuP5Et6sXLm2B
+VaIPVL2qOYCZ2QF3qehORtECgYEAgp+8UQEYVGtLY5g8Am41JBvhhuv4m9IypG6N
+PD5FDO1rwCaXXDRTXpZqAgVwQdrzxiBPg4Wq/pF9DbTCYCYV5r20Vv2l+MQ5dJoJ
+r4TOATeP24EDuNJioksDe4hLd4cl5reLDmhJ6BgGoSL9azRoFX3xtHtZibO9PVnI
+aKMFsvkCgYBuyxlbngBYAGLm62T1sQqaEzNLGVZKx7S7kNIr6aTpi9DRReOjlHgP
+Xb/f9ckxDcTgk9JFg5dkQMWlZhhLVqxtpiCU9cHjLHMfCWB8cs86fvbGeqTr0L80
+HcVvnC5W3vlQ90eb5WjNx9l9WeOklS4qrNkCJt931bl3P7CH39Fc5Q==
+-----END RSA PRIVATE KEY-----
diff --git a/docs/examples/pubkey.der b/docs/examples/pubkey.der
new file mode 100644
index 0000000000000000000000000000000000000000..61461d9e122d6e58f725d2c5c7dff449c7446dfb
Binary files /dev/null and b/docs/examples/pubkey.der differ
diff --git a/pom.xml b/pom.xml
index 03959660febf9622addd523ce78d327a341d6239..cc64b4c6696e121b80af8435e78057b3f32d49cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -88,6 +88,18 @@
false
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ com.patrikdufresne.license.Main
+
+
+
+
diff --git a/src/main/java/com/patrikdufresne/license/Main.java b/src/main/java/com/patrikdufresne/license/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..d70ccd1e97168629e394632ecad1de34a4da346e
--- /dev/null
+++ b/src/main/java/com/patrikdufresne/license/Main.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright(C) 2018 Patrik Dufresne Service Logiciel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package com.patrikdufresne.license;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Main entry point when this library is executed from command line.
+ *
+ * @author Patrik Dufresne
+ *
+ */
+public class Main {
+
+ public static void create(String publicKey, String privateKey, String name, String email, String expiration, String output)
+ throws GeneralSecurityException,
+ IOException {
+ if (publicKey == null) {
+ throw new IllegalArgumentException("public key is missing");
+ }
+ if (privateKey == null) {
+ throw new IllegalArgumentException("private key is missing");
+ }
+ if (expiration == null) {
+ throw new IllegalArgumentException("expiration date is missing");
+ }
+
+ // Create license obj
+ License license = new License();
+ license.setProperty(License.NAME, name);
+ license.setProperty(License.EMAIL, email);
+ license.setProperty(License.LICENSE_TYPE, License.TYPE_TRIAL);
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date d;
+ try {
+ d = dateFormat.parse(expiration);
+ } catch (ParseException e1) {
+ throw new IllegalArgumentException("Wrong date value: " + expiration);
+ }
+ license.setExpiration(d);
+
+ // Create the license file
+ LicenseManager manager = new LicenseManager(publicKey, privateKey);
+ manager.writeLicense(license, new File(output));
+
+ }
+
+ public static void main(String[] args) throws GeneralSecurityException {
+ if (args.length == 0) {
+ usage();
+ return;
+ }
+ // Parse arguments
+ String publicKey = null;
+ String privateKey = null;
+ String name = "";
+ String email = "";
+ String expiration = null;
+ String file = "application.lic";
+
+ String action = args[0];
+ if (!action.equals("create") && !action.equals("validate")) {
+ usage();
+ return;
+ }
+ int idx = 1;
+ while (idx < args.length) {
+ switch (args[idx]) {
+ case "-p":
+ case "--public":
+ idx++;
+ publicKey = args[idx];
+ break;
+ case "-P":
+ case "--private":
+ idx++;
+ privateKey = args[idx];
+ break;
+ case "-n":
+ case "--name":
+ idx++;
+ name = args[idx];
+ break;
+ case "-m":
+ case "--email":
+ idx++;
+ email = args[idx];
+ break;
+ case "-e":
+ case "--expiration":
+ idx++;
+ expiration = args[idx];
+ break;
+ case "-f":
+ case "--file":
+ idx++;
+ file = args[idx];
+ break;
+ default:
+ System.err.println("unknown arguments: " + args[idx]);
+ usage();
+ return;
+ }
+ idx++;
+ }
+ // Take action.
+ try {
+ if (action.equals("create")) {
+ create(publicKey, privateKey, name, email, expiration, file);
+ System.out.println("license " + file + " created");
+ } else if (action.equals("validate")) {
+ try {
+ LicenseManager.validate(new FileInputStream(publicKey), new File(file));
+ } catch (LicenseException e) {
+ System.out.println("license " + file + " invalid: " + e.getMessage());
+ System.exit(1);
+ }
+ System.out.println("license " + file + " valid");
+ } else {
+ usage();
+ }
+ } catch (IOException | IllegalArgumentException e) {
+ System.err.println(e.getMessage());
+ System.exit(1);
+ }
+
+ }
+
+ public static void usage() {
+ System.out.println("usage:");
+ System.out.println(" create -p pubkey.der -P privkey.der [-n name] [-m email] -e YYYY-mm-dd [-f application.lic]");
+ System.out.println(" validate -p pubkey.der [-f application.lic]");
+ System.out.println("");
+ System.out.println(" -p, --public define the public key file in DER format");
+ System.out.println(" -P, --private define the private key file file in DER format");
+ System.out.println(" -n, --name name to be stored in the license file (optional)");
+ System.out.println(" -m, --mail email to be stored in the license file (optional)");
+ System.out.println(" -e, --expiration expiration date in YYYY-mm-dd format");
+ System.out.println(" -f, --file the license file to be created or validated (default: application.lic)");
+ System.exit(1);
+ }
+
+}