From 146a0fb8b0e90f9196e569152f649baf60d6cc8f Mon Sep 17 00:00:00 2001
From: Joaquín Reñé <jrene@curisit.net>
Date: Tue, 07 Oct 2025 14:52:57 +0000
Subject: [PATCH] #4410 - Comments on classes
---
securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java | 287 +++++++++++++++++++++++++++++++++++----------------------
1 files changed, 177 insertions(+), 110 deletions(-)
diff --git a/securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java b/securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java
index 7159ddc..a2115d6 100644
--- a/securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java
+++ b/securis/src/main/java/net/curisit/securis/services/helpers/LicenseHelper.java
@@ -1,3 +1,6 @@
+/*
+ * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved.
+ */
package net.curisit.securis.services.helpers;
import java.io.File;
@@ -30,128 +33,192 @@
import net.curisit.securis.services.exception.SeCurisServiceException;
import net.curisit.securis.services.exception.SeCurisServiceException.ErrorCodes;
+/**
+ * LicenseHelper
+ * <p>
+ * Stateless utility component for license lifecycle operations and helpers:
+ * - cancelation with history auditing
+ * - license resolution and validity checks
+ * - license file generation in a temp directory
+ * - metadata extraction and expiration date computation from packs
+ * - sequential code suffix allocation per pack
+ *
+ * Thread-safety: ApplicationScoped, stateless.
+ *
+ * @author JRA
+ * Last reviewed by JRA on Oct 5, 2025.
+ */
@ApplicationScoped
public class LicenseHelper {
- @SuppressWarnings("unused")
- private static final Logger LOG = LogManager.getLogger(LicenseHelper.class);
- private static final long MS_PER_DAY = 24L * 3600L * 1000L;
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LogManager.getLogger(LicenseHelper.class);
- @Inject
- private UserHelper userHelper;
+ /** Milliseconds per day (used to derive expiration dates). */
+ private static final long MS_PER_DAY = 24L * 3600L * 1000L;
- /**
- * Cancel the license
- *
- * @param lic
- * @param em
- */
- public void cancelLicense(License lic, String reason, BasicSecurityContext bsc, EntityManager em) throws SeCurisServiceException {
- lic.setStatus(LicenseStatus.CANCELLED);
- lic.setCancelledById(bsc.getUserPrincipal().getName());
- lic.setModificationTimestamp(new Date());
- em.persist(lic);
+ @Inject private UserHelper userHelper;
- em.persist(createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.CANCEL, "Cancellation reason: " + reason));
- }
+ /**
+ * cancelLicense
+ * <p>
+ * Transitions a license to CANCELLED, records who canceled it and why,
+ * and appends a {@link LicenseHistory} entry.
+ *
+ * @param lic Target license (managed).
+ * @param reason Human-readable cancellation reason (auditable).
+ * @param bsc Current security context (used to identify the user).
+ * @param em Entity manager to persist changes.
+ * @throws SeCurisServiceException never thrown here, declared for symmetry with callers.
+ */
+ public void cancelLicense(License lic, String reason, BasicSecurityContext bsc, EntityManager em) throws SeCurisServiceException {
+ lic.setStatus(LicenseStatus.CANCELLED);
+ lic.setCancelledById(bsc.getUserPrincipal().getName());
+ lic.setModificationTimestamp(new Date());
+ em.persist(lic);
- /**
- * Validates that the passed license exists and is still valid
- *
- * @param licBean
- * @param em
- * @return The License instance in DB
- * @throws SeCurisServiceException
- */
- public License getActiveLicenseFromDB(LicenseBean licBean, EntityManager em) throws SeCurisServiceException {
- License lic = License.findLicenseByCode(licBean.getLicenseCode(), em);
- if (lic == null) {
- throw new SeCurisServiceException(ErrorCodes.LICENSE_DATA_IS_NOT_VALID, "Current license code doesn't exist");
- }
- if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
- throw new SeCurisServiceException(ErrorCodes.LICENSE_DATA_IS_NOT_VALID, "Current license in not active");
- }
- return lic;
- }
+ em.persist(createLicenseHistoryAction(lic, userHelper.getUser(bsc, em), LicenseHistory.Actions.CANCEL, "Cancellation reason: " + reason));
+ }
- public LicenseHistory createLicenseHistoryAction(License lic, User user, String action, String comments) {
- LicenseHistory lh = new LicenseHistory();
- lh.setLicense(lic);
- lh.setUser(user);
- lh.setCreationTimestamp(new Date());
- lh.setAction(action);
- lh.setComments(comments);
- return lh;
- }
+ /**
+ * getActiveLicenseFromDB
+ * <p>
+ * Resolve license by code and verify that it's ACTIVE or PRE_ACTIVE.
+ *
+ * @param licBean License bean containing the code to check.
+ * @param em EntityManager for DB access.
+ * @return The managed {@link License} instance.
+ * @throws SeCurisServiceException if code not found or license not in an active-ish state.
+ */
+ public License getActiveLicenseFromDB(LicenseBean licBean, EntityManager em) throws SeCurisServiceException {
+ License lic = License.findLicenseByCode(licBean.getLicenseCode(), em);
+ if (lic == null) {
+ throw new SeCurisServiceException(ErrorCodes.LICENSE_DATA_IS_NOT_VALID, "Current license code doesn't exist");
+ }
+ if (lic.getStatus() != LicenseStatus.ACTIVE && lic.getStatus() != LicenseStatus.PRE_ACTIVE) {
+ throw new SeCurisServiceException(ErrorCodes.LICENSE_DATA_IS_NOT_VALID, "Current license in not active");
+ }
+ return lic;
+ }
- public LicenseHistory createLicenseHistoryAction(License lic, User user, String action) {
- return createLicenseHistoryAction(lic, user, action, null);
- }
+ /**
+ * createLicenseHistoryAction
+ * <p>
+ * Helper to build a {@link LicenseHistory} entry.
+ *
+ * @param lic License affected.
+ * @param user User performing the action.
+ * @param action Action code (see {@link LicenseHistory.Actions}).
+ * @param comments Optional comments, can be null.
+ * @return transient {@link LicenseHistory} ready to persist.
+ */
+ public LicenseHistory createLicenseHistoryAction(License lic, User user, String action, String comments) {
+ LicenseHistory lh = new LicenseHistory();
+ lh.setLicense(lic);
+ lh.setUser(user);
+ lh.setCreationTimestamp(new Date());
+ lh.setAction(action);
+ lh.setComments(comments);
+ return lh;
+ }
- /**
- * Create a license file in a temporary directory
- *
- * @param lic
- * @param licFileName
- * @return
- * @throws IOException
- */
- public File createTemporaryLicenseFile(License lic, String licFileName) throws IOException {
- File f = Files.createTempDirectory("securis-server").toFile();
- f = new File(f, licFileName);
- FileUtils.writeStringToFile(f, lic.getLicenseData(), StandardCharsets.UTF_8);
- return f;
- }
+ /**
+ * createLicenseHistoryAction
+ * <p>
+ * Overload without comments.
+ *
+ * @param lic License affected.
+ * @param user User performing the action.
+ * @param action Action code.
+ * @return transient {@link LicenseHistory}.
+ */
+ public LicenseHistory createLicenseHistoryAction(License lic, User user, String action) {
+ return createLicenseHistoryAction(lic, user, action, null);
+ }
- public Map<String, Object> extractPackMetadata(Set<PackMetadata> packMetadata) {
- Map<String, Object> metadata = new HashMap<>();
- for (PackMetadata md : packMetadata) {
- metadata.put(md.getKey(), md.getValue());
- }
+ /**
+ * createTemporaryLicenseFile
+ * <p>
+ * Materializes the license payload into a temporary file for emailing/download.
+ * The file is created under a unique temporary directory.
+ *
+ * Caller is responsible for deleting the file and its parent directory.
+ *
+ * @param lic License whose JSON/XML/text payload is in {@code getLicenseData()}.
+ * @param licFileName Desired file name (e.g. "license.lic").
+ * @return A {@link File} pointing to the newly created file.
+ * @throws IOException If the temporary directory or file cannot be created/written.
+ */
+ public File createTemporaryLicenseFile(License lic, String licFileName) throws IOException {
+ File f = Files.createTempDirectory("securis-server").toFile();
+ f = new File(f, licFileName);
+ FileUtils.writeStringToFile(f, lic.getLicenseData(), StandardCharsets.UTF_8);
+ return f;
+ }
- return metadata;
- }
+ /**
+ * extractPackMetadata
+ * <p>
+ * Converts pack metadata set to a map for license generation.
+ *
+ * @param packMetadata Set of {@link PackMetadata}.
+ * @return Map with keys/values copied from metadata entries.
+ */
+ public Map<String, Object> extractPackMetadata(Set<PackMetadata> packMetadata) {
+ Map<String, Object> metadata = new HashMap<>();
+ for (PackMetadata md : packMetadata) {
+ metadata.put(md.getKey(), md.getValue());
+ }
+ return metadata;
+ }
- /**
- * If the action is a renew the expiration date is got form pack end valid
- * date, if the action is a pre-activation the expiration date is calculated
- * using the pack default valid period
- *
- * @param pack
- * @param isPreActivation
- * @return
- */
- public Date getExpirationDateFromPack(Pack pack, boolean isPreActivation) {
- Long validPeriod;
- if (pack.getEndValidDate().before(new Date())) {
- throw new CurisRuntimeException("Pack end valid period is reached, no new licenses can be activated.");
- }
- if (isPreActivation) {
- validPeriod = pack.getPreactivationValidPeriod() * MS_PER_DAY;
- } else {
- if (pack.getRenewValidPeriod() <= 0) {
- return pack.getEndValidDate();
- }
- long renewPeriod = pack.getRenewValidPeriod() * MS_PER_DAY;
- long expirationPeriod = pack.getEndValidDate().getTime() - new Date().getTime();
- validPeriod = renewPeriod < expirationPeriod ? renewPeriod : expirationPeriod;
- }
- Date expirationDate = new Date(new Date().getTime() + validPeriod);
- return expirationDate;
- }
+ /**
+ * getExpirationDateFromPack
+ * <p>
+ * Computes license expiration date depending on action type:
+ * - Pre-activation: {@code preactivationValidPeriod} days from now.
+ * - Renew/Activation: min(renewValidPeriod days, pack end date - now).
+ * Fails fast if pack end date is already in the past.
+ *
+ * @param pack Pack with policy data.
+ * @param isPreActivation Whether the operation is a pre-activation.
+ * @return Calculated expiration {@link Date}.
+ * @throws CurisRuntimeException if the pack's end date is in the past.
+ */
+ public Date getExpirationDateFromPack(Pack pack, boolean isPreActivation) {
+ Long validPeriod;
+ if (pack.getEndValidDate().before(new Date())) {
+ throw new CurisRuntimeException("Pack end valid period is reached, no new licenses can be activated.");
+ }
+ if (isPreActivation) {
+ validPeriod = pack.getPreactivationValidPeriod() * MS_PER_DAY;
+ } else {
+ if (pack.getRenewValidPeriod() <= 0) {
+ return pack.getEndValidDate();
+ }
+ long renewPeriod = pack.getRenewValidPeriod() * MS_PER_DAY;
+ long expirationPeriod = pack.getEndValidDate().getTime() - new Date().getTime();
+ validPeriod = renewPeriod < expirationPeriod ? renewPeriod : expirationPeriod;
+ }
+ Date expirationDate = new Date(new Date().getTime() + validPeriod);
+ return expirationDate;
+ }
- /**
- * Get the next free code suffis for a given Pack
- *
- * @param packId
- * @param em
- * @return
- */
- public int getNextCodeSuffix(int packId, EntityManager em) {
- TypedQuery<Integer> query = em.createNamedQuery("last-code-suffix-used-in-pack", Integer.class);
- query.setParameter("packId", packId);
- Integer lastCodeSuffix = query.getSingleResult();
- return lastCodeSuffix == null ? 1 : lastCodeSuffix + 1;
- }
-
+ /**
+ * getNextCodeSuffix
+ * <p>
+ * Retrieves the last used code suffix for a given pack and returns the next one.
+ * If none found, returns 1.
+ *
+ * @param packId Pack identifier.
+ * @param em EntityManager to query the DB.
+ * @return Next sequential suffix (>= 1).
+ */
+ public int getNextCodeSuffix(int packId, EntityManager em) {
+ TypedQuery<Integer> query = em.createNamedQuery("last-code-suffix-used-in-pack", Integer.class);
+ query.setParameter("packId", packId);
+ Integer lastCodeSuffix = query.getSingleResult();
+ return lastCodeSuffix == null ? 1 : lastCodeSuffix + 1;
+ }
}
+
--
Gitblit v1.3.2