diff --git a/pom.xml b/pom.xml
index 72d27143e..e11f547e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -150,6 +150,8 @@
3.1.1-SNAPSHOT
3.0.2-SNAPSHOT
+ false
+ ${project.build.directory}/license
@@ -319,6 +321,28 @@
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.6.2
+
+
+ fetch-community-license
+ prepare-package
+
+ java
+
+
+ ${license.fetch.skip}
+ io.mapsmessaging.license.tools.LicenseFetcher
+ compile
+
+ ${license.fetch.dir}
+
+
+
+
+
org.apache.maven.plugins
@@ -1194,6 +1218,18 @@
5.5.7
test
+
+ org.java-websocket
+ Java-WebSocket
+ 1.5.3
+
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ 4.12.0
+ test
+
diff --git a/src/main/assemble/scripts.xml b/src/main/assemble/scripts.xml
index e9b0872a5..8e378429c 100644
--- a/src/main/assemble/scripts.xml
+++ b/src/main/assemble/scripts.xml
@@ -82,6 +82,13 @@
+
+ ${project.basedir}/target/license/
+ conf
+
+ *.lic
+
+
${project.basedir}/src/main/resources/
diff --git a/src/main/java/io/mapsmessaging/license/LicenseController.java b/src/main/java/io/mapsmessaging/license/LicenseController.java
index cae1174ba..bc1088ff4 100644
--- a/src/main/java/io/mapsmessaging/license/LicenseController.java
+++ b/src/main/java/io/mapsmessaging/license/LicenseController.java
@@ -19,8 +19,6 @@
package io.mapsmessaging.license;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import global.namespace.fun.io.bios.BIOS;
import global.namespace.truelicense.api.License;
@@ -33,20 +31,18 @@
import io.mapsmessaging.logging.ServerLogMessages;
import io.mapsmessaging.utilities.GsonFactory;
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
+import java.io.File;
import java.time.Instant;
import java.time.ZoneId;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
public class LicenseController {
- private static final String LICENSE_SERVER_URL = "https://license.mapsmessaging.io/api/v1/license";
-
- private static final String LICENSE_KEY="license_";
+ private static final String LICENSE_KEY = "license_";
private final List licenses;
private final Logger logger = LoggerFactory.getLogger(LicenseController.class);
@@ -56,15 +52,23 @@ public LicenseController(String licensePath, String uniqueId, UUID serverUUID) {
if (!licenseDir.exists() || !licenseDir.isDirectory()) {
throw new IllegalArgumentException("Invalid license path: " + licensePath);
}
+
installLicenses(licenseDir);
licenses = loadInstalledLicenses(licenseDir);
- if(licenses.isEmpty()) {
- fetchLicenseFromServer(licenseDir, uniqueId, serverUUID);
+
+ if (licenses.isEmpty()) {
+ boolean fetched = fetchLicenseFromServer(licenseDir, uniqueId, serverUUID);
+ if (!fetched) {
+ LicenseFileStore licenseFileStore = new LicenseFileStore(logger);
+ licenseFileStore.ensureFallbackLicensePresent(licenseDir);
+ }
+
installLicenses(licenseDir);
licenses.addAll(loadInstalledLicenses(licenseDir));
}
+
Gson gson = GsonFactory.getInstance().getPrettyGson();
- for(FeatureDetails feature : licenses) {
+ for (FeatureDetails feature : licenses) {
logger.log(ServerLogMessages.LICENSE_FEATURES_AVAILABLE, gson.toJson(feature.getFeature()));
}
}
@@ -73,11 +77,6 @@ public FeatureManager getFeatureManager() {
return new FeatureManager(licenses);
}
- /**
- * Installs any licenses that have not yet been installed.
- *
- * @param licenseDir Directory containing license files.
- */
private void installLicenses(File licenseDir) {
File[] files = licenseDir.listFiles((dir, name) -> name.startsWith(LICENSE_KEY) && name.endsWith(".lic"));
if (files == null) {
@@ -94,18 +93,16 @@ private void installLicenses(File licenseDir) {
}
}
-
- private void processLicenseFile(File licenseFile, String edition, File installedFile) {
+ private void processLicenseFile(File licenseFile, String edition, File installedFile) {
try {
LicenseManager manager = getLicenseManager(edition);
- if(manager != null) {
+ if (manager != null) {
logger.log(ServerLogMessages.LICENSE_INSTALLING, edition);
manager.install(manager.parameters().encryption().source(BIOS.file(licenseFile)));
- if(!licenseFile.renameTo(installedFile)){
+ if (!licenseFile.renameTo(installedFile)) {
logger.log(ServerLogMessages.LICENSE_FILE_RENAME_FAILED, licenseFile.getAbsolutePath(), installedFile.getAbsolutePath());
}
- }
- else{
+ } else {
logger.log(ServerLogMessages.LICENSE_MANAGER_NOT_FOUND, edition);
}
} catch (IllegalArgumentException | LicenseManagementException e) {
@@ -114,22 +111,19 @@ private void processLicenseFile(File licenseFile, String edition, File installe
}
private LicenseManager getLicenseManager(String edition) {
- for(LicenseManager manager : LicenseManager.values()) {
- if(edition.equalsIgnoreCase(manager.name())) {
+ for (LicenseManager manager : LicenseManager.values()) {
+ if (edition.equalsIgnoreCase(manager.name())) {
return manager;
}
}
return null;
}
- /**
- * Scans installed licenses and loads them.
- *
- * @param licenseDir Directory containing installed license files.
- */
- private List loadInstalledLicenses(File licenseDir) {
+ private List loadInstalledLicenses(File licenseDir) {
File[] files = licenseDir.listFiles((dir, name) -> name.startsWith(LICENSE_KEY) && name.endsWith(".lic_installed"));
- if (files == null) return new ArrayList<>();
+ if (files == null) {
+ return new ArrayList<>();
+ }
List licenseList = new ArrayList<>();
@@ -137,17 +131,16 @@ private List loadInstalledLicenses(File licenseDir) {
String edition = extractEdition(installedFile.getName());
try {
LicenseManager manager = getLicenseManager(edition.toUpperCase());
- if(manager != null) {
+ if (manager != null) {
logger.log(ServerLogMessages.LICENSE_LOADING, edition);
- if(!processLicense( manager.load(), licenseList)){
+ if (!processLicense(manager.load(), licenseList)) {
logger.log(ServerLogMessages.LICENSE_UNINSTALLING, edition);
- if(!installedFile.delete()){
+ if (!installedFile.delete()) {
logger.log(ServerLogMessages.LICENSE_FAILED_DELETE_FILE, installedFile.getAbsolutePath());
}
manager.uninstall();
}
- }
- else{
+ } else {
logger.log(ServerLogMessages.LICENSE_MANAGER_NOT_FOUND, edition);
}
} catch (IllegalArgumentException | LicenseManagementException e) {
@@ -157,127 +150,70 @@ private List loadInstalledLicenses(File licenseDir) {
return licenseList;
}
- private boolean processLicense(License license,List licenseList) {
+ @SuppressWarnings("unchecked")
+ private boolean processLicense(License license, List licenseList) {
long now = System.currentTimeMillis();
- if(license != null) {
+ if (license != null) {
if (license.getNotBefore().getTime() < now && license.getNotAfter().getTime() > now) {
Gson gson = GsonFactory.getInstance().getSimpleGson();
Map extraData = (Map) license.getExtra();
String json = gson.toJson(extraData);
Features features = gson.fromJson(json, Features.class);
+
Date after = license.getNotAfter();
Date before = license.getNotBefore();
Date issued = license.getIssued();
String info = license.getInfo();
String who = license.getIssuer().getName();
+
FeatureDetails featureDetails = new FeatureDetails();
featureDetails.setFeature(features);
featureDetails.setExpiry(Instant.ofEpochMilli(after.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime());
featureDetails.setInfo(info);
licenseList.add(featureDetails);
-
- logger.log(ServerLogMessages.LICENSE_LOADED, info, who, issued, after, before, gson.toJson(extraData));
+ logger.log(ServerLogMessages.LICENSE_LOADED, info, who, issued, after, before, gson.toJson(extraData));
return true;
} else {
logger.log(ServerLogMessages.LICENSE_EXPIRED, license.getInfo(), license.getNotBefore(), license.getNotAfter());
- return (license.getNotAfter().getTime() > now); // Do NOT delete the license if it is still valid but can not yet be used
+ return (license.getNotAfter().getTime() > now);
}
}
return false;
}
- private void fetchLicenseFromServer(File licenseDir, String uniqueId, UUID serverUUID) {
+ private boolean fetchLicenseFromServer(File licenseDir, String uniqueId, UUID serverUUID) {
try {
LicenseConfig licenseConfig = new LicenseConfig();
licenseConfig = (LicenseConfig) licenseConfig.load(null);
String clientSecret = licenseConfig.getClientSecret();
String clientName = licenseConfig.getClientName();
- URI uri = URI.create(LICENSE_SERVER_URL);
- URL url = uri.toURL();
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setRequestMethod("POST");
- connection.setDoOutput(true);
- connection.setRequestProperty("Content-Type", "application/json");
-
-// Build JSON request body
- String jsonBody = String.format(
- "{\"clientName\":\"%s\",\"clientSecret\":\"%s\",\"uniqueServerId\":\"%s\",\"serverUUID\":\"%s\"}",
- clientName, clientSecret, uniqueId, serverUUID.toString()
- );
- logger.log(ServerLogMessages.LICENSE_CONTACTING_SERVER, clientName);
- try (OutputStream os = connection.getOutputStream()) {
- os.write(jsonBody.getBytes(StandardCharsets.UTF_8));
+
+ LicenseServerClient licenseServerClient = new LicenseServerClient(logger);
+ List serverLicenses =
+ licenseServerClient.fetchLicenses(clientName, clientSecret, uniqueId, serverUUID);
+
+ if (serverLicenses.isEmpty()) {
+ return false;
}
- // Read response
- int responseCode = connection.getResponseCode();
- if (responseCode == 200) {
- try (InputStream is = connection.getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+ LicenseFileStore licenseFileStore = new LicenseFileStore(logger);
+ boolean savedAny = false;
- StringBuilder response = new StringBuilder();
- String line;
- while ((line = reader.readLine()) != null) {
- response.append(line);
- }
- // Parse response
- List