diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionUpdateManager.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicenseUpdater.java similarity index 61% rename from application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionUpdateManager.java rename to application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicenseUpdater.java index 29876b2..431e983 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionUpdateManager.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicenseUpdater.java @@ -19,6 +19,29 @@ */ package com.xwiki.licensing; -public interface LicensedExtensionUpdateManager +import org.xwiki.component.annotation.Role; +import org.xwiki.extension.ExtensionId; +import org.xwiki.stability.Unstable; + +/** + * Description in progress. + * + * @version $Id$ + * @since 1.27 + */ +@Role +@Unstable +public interface LicenseUpdater { + /** + * Make request to store for renewing this extension's license. Description in progress. + * + * @param extensionId extension for which the license needs an update + */ + void renewLicense(ExtensionId extensionId); + + /** + * Retrieve licenses updates from the XWiki Store. + */ + void getLicensesUpdates(); } diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionManager.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionManager.java index b43b853..9e2fd87 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionManager.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensedExtensionManager.java @@ -20,9 +20,11 @@ package com.xwiki.licensing; import java.util.Collection; +import java.util.Set; import org.xwiki.component.annotation.Role; import org.xwiki.extension.ExtensionId; +import org.xwiki.extension.InstalledExtension; import org.xwiki.stability.Unstable; /** @@ -70,4 +72,14 @@ public interface LicensedExtensionManager * @since 1.21.1 */ void invalidateMandatoryLicensedExtensionsCache(); + + /** + * Get the list of licensed dependencies of an extension from a specific namespace. + * + * @param installedExtension the installed extension for which to look for licensed dependencies + * @param namespace the namespace where to look for dependencies + * @return a set of installed licensed dependencies + * @since 1.27 + */ + Set getLicensedDependencies(InstalledExtension installedExtension, String namespace); } diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensingConfiguration.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensingConfiguration.java index eb0db1f..093ec38 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensingConfiguration.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensingConfiguration.java @@ -62,6 +62,7 @@ public interface LicensingConfiguration * Get the URL used in renewing an existing license of an extension from store. * * @return the URL used in renewing an existing license or null if the value of the property is not filled up + * @since 1.27 */ String getStoreLicenseRenewURL(); diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenew.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicenseUpdater.java similarity index 53% rename from application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenew.java rename to application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicenseUpdater.java index 2160fcf..c8e8e9d 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenew.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicenseUpdater.java @@ -19,12 +19,14 @@ */ package com.xwiki.licensing.internal; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; -import java.util.Collection; -import java.util.Set; -import java.util.Stack; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; @@ -32,22 +34,30 @@ import org.apache.http.client.utils.URIBuilder; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; -import org.xwiki.extension.ExtensionDependency; +import org.xwiki.crypto.BinaryStringEncoder; import org.xwiki.extension.ExtensionId; -import org.xwiki.extension.InstalledExtension; import org.xwiki.extension.repository.InstalledExtensionRepository; import org.xwiki.instance.InstanceIdManager; +import org.xwiki.properties.converter.Converter; +import com.fasterxml.jackson.databind.ObjectMapper; import com.xpn.xwiki.XWikiContext; +import com.xwiki.licensing.License; +import com.xwiki.licensing.LicenseManager; +import com.xwiki.licensing.LicenseUpdater; import com.xwiki.licensing.LicensedExtensionManager; import com.xwiki.licensing.LicensingConfiguration; +import com.xwiki.licensing.Licensor; /** - * In progress: these methods might be moved to other components at the refactoring step. + * Handle license updates processes. Description in progress. + * + * @version $Id$ + * @since 1.27 */ -@Component(roles = LicenseRenew.class) +@Component @Singleton -public class LicenseRenew +public class DefaultLicenseUpdater implements LicenseUpdater { private static final String FEATURE_ID = "featureId"; @@ -72,37 +82,25 @@ public class LicenseRenew private Provider instanceIdManagerProvider; @Inject - private TrialLicenseGenerator trialLicenseGenerator; + private Provider licensorProvider; - public void getLicensedDependencies(Set licensedDependencies, Stack dependencyPath, - InstalledExtension installedExtension, String namespace) - { - Collection dependencies = installedExtension.getDependencies(); - - for (ExtensionDependency dep : dependencies) { - InstalledExtension installedDep = - installedExtensionRepository.getInstalledExtension(dep.getId(), namespace); - if (installedDep == null || licensedDependencies.contains(installedDep.getId()) - || dependencyPath.search(installedDep.getId()) > 0) - { - return; - } + @Inject + private Provider licenseManagerProvider; - if (licensedExtensionManager.getLicensedExtensions().contains(installedDep.getId())) { - licensedDependencies.add(installedDep.getId()); - } + @Inject + @Named("Base64") + private BinaryStringEncoder base64decoder; - dependencyPath.push(installedDep.getId()); - getLicensedDependencies(licensedDependencies, dependencyPath, installedDep, namespace); - } - } + @Inject + private Converter converter; + @Override public void renewLicense(ExtensionId extensionId) { try { URL licenseRenewURL = getLicenseRenewURL(extensionId); if (licenseRenewURL == null) { - logger.debug("Failed to add renew license for [{}] because the licensor configuration is not complete. " + logger.debug("Failed to renew license for [{}] because the licensor configuration is not complete. " + "Check your store license renew URL and owner details.", extensionId.getId()); return; } @@ -114,8 +112,7 @@ public void renewLicense(ExtensionId extensionId) logger.debug("Failed to renew license for [{}] on store.", extensionId.getId()); } else { logger.debug("License renewed for [{}]", extensionId.getId()); - // This will be moved to other component - //trialLicenseGenerator.updateLicenses(); + // getLicensesUpdates(); } } catch (Exception e) { logger.warn("Failed to update license for [{}]. Root cause is [{}]", extensionId, @@ -123,6 +120,65 @@ public void renewLicense(ExtensionId extensionId) } } + @Override + @SuppressWarnings("unchecked") + public void getLicensesUpdates() + { + try { + URL licensesUpdateURL = getLicensesUpdatesURL(); + if (licensesUpdateURL == null) { + logger.warn("Failed to update licenses because the licensor configuration is not complete. " + + "Check your store update URL."); + return; + } + + XWikiContext xcontext = contextProvider.get(); + String licensesUpdateResponse = xcontext.getWiki().getURLContent(licensesUpdateURL.toString(), xcontext); + ObjectMapper objectMapper = new ObjectMapper(); + + List retriedLicenses = (List) objectMapper.readValue(licensesUpdateResponse, Object.class); + for (String license : retriedLicenses) { + License retrivedLicense = converter.convert(License.class, base64decoder.decode(license)); + if (retrivedLicense != null) { + licenseManagerProvider.get().add(retrivedLicense); + } + } + } catch (URISyntaxException | IOException e) { + logger.warn("Error while updating licenses. Root cause [{}]", ExceptionUtils.getRootCauseMessage(e)); + } + } + + /** + * Construct the URL for updating licenses. + * + * @return the URL for updating licenses, or null if it cannot be constructed + * @throws URISyntaxException if the URL is not valid + * @throws MalformedURLException if an error occurred while constructing the URL + */ + private URL getLicensesUpdatesURL() throws URISyntaxException, MalformedURLException + { + String storeUpdateURL = licensingConfig.getStoreUpdateURL(); + // In case the property has no filled value, the URL cannot be constructed. + if (storeUpdateURL == null) { + return null; + } + + URIBuilder builder = new URIBuilder(storeUpdateURL); + builder.addParameter(INSTANCE_ID, instanceIdManagerProvider.get().getInstanceId().toString()); + builder.addParameter("outputSyntax", "plain"); + + for (ExtensionId paidExtensionId : licensedExtensionManager.getMandatoryLicensedExtensions()) { + builder.addParameter(FEATURE_ID, paidExtensionId.getId()); + + License license = licensorProvider.get().getLicense(paidExtensionId); + if (license != null && !License.UNLICENSED.equals(license)) { + builder.addParameter(String.format("expirationDate:%s", paidExtensionId.getId()), + Long.toString(license.getExpirationDate())); + } + } + return builder.build().toURL(); + } + private URL getLicenseRenewURL(ExtensionId extensionId) throws Exception { String storeLicenseRenewURL = licensingConfig.getStoreLicenseRenewURL(); diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensedExtensionManager.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensedExtensionManager.java index 8f6f1bc..4d82026 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensedExtensionManager.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensedExtensionManager.java @@ -40,6 +40,7 @@ import org.xwiki.extension.InstalledExtension; import org.xwiki.extension.ResolveException; import org.xwiki.extension.repository.InstalledExtensionRepository; +import org.xwiki.stability.Unstable; import com.xwiki.licensing.LicensedExtensionManager; import com.xwiki.licensing.LicensedFeatureId; @@ -196,4 +197,44 @@ public void invalidateMandatoryLicensedExtensionsCache() { this.cachedMandatoryLicensedExtensions = null; } + + @Override + @Unstable + public Set getLicensedDependencies(InstalledExtension installedExtension, String namespace) + { + Set licensedDependencies = new HashSet<>(); + Set verifiedExtensions = new HashSet<>(); + + getLicensedDependencies(installedExtension, namespace, getLicensedExtensions(), licensedDependencies, + verifiedExtensions); + logger.debug("Found licensed dependencies for extension [{}] : [{}]", installedExtension.getId(), + licensedDependencies); + + return licensedDependencies; + } + + private void getLicensedDependencies(InstalledExtension installedExtension, String namespace, + Collection installedLicensedExtensions, Set licensedDependencies, + Set verifiedExtensions) + { + Collection dependencies = installedExtension.getDependencies(); + + for (ExtensionDependency dep : dependencies) { + InstalledExtension installedDep = + installedExtensionRepository.getInstalledExtension(dep.getId(), namespace); + if (installedDep == null || licensedDependencies.contains(installedDep.getId()) + || verifiedExtensions.contains(installedDep.getId())) + { + return; + } + + if (installedLicensedExtensions.contains(installedDep.getId())) { + licensedDependencies.add(installedDep.getId()); + } + + verifiedExtensions.add(installedDep.getId()); + getLicensedDependencies(installedDep, namespace, installedLicensedExtensions, licensedDependencies, + verifiedExtensions); + } + } } diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensingConfiguration.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensingConfiguration.java index 8ea9afb..f141336 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensingConfiguration.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensingConfiguration.java @@ -131,6 +131,12 @@ public String getLicensingOwnerEmail() return this.ownerConfig.getProperty("email"); } + @Override + public String getStoreLicenseRenewURL() + { + return this.storeConfig.getProperty("storeLicenseRenewURL"); + } + @SuppressWarnings("unchecked") private List convertObjectToStringList(Object list) { diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/GetTrialLicenseListener.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/GetTrialLicenseListener.java index b5dae55..d23321d 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/GetTrialLicenseListener.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/GetTrialLicenseListener.java @@ -64,6 +64,9 @@ public class GetTrialLicenseListener implements EventListener @Inject private LicensedExtensionManager licensedExtensionManager; + @Inject + private DefaultLicenseUpdater licenseUpdater; + @Override public List getEvents() { @@ -83,7 +86,7 @@ public void onEvent(Event event, Object source, Object data) licensedExtensionManager.invalidateMandatoryLicensedExtensionsCache(); // Retrieve license updates to be sure that we don't override an existing license. - trialLicenseGenerator.updateLicenses(); + licenseUpdater.getLicensesUpdates(); for (ExtensionId extensionId : extensions) { InstalledExtension installedExtension = installedExtensionRepository.getInstalledExtension(extensionId); diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenewListener.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenewListener.java index 4c6c820..e644447 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenewListener.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/LicenseRenewListener.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.Stack; import javax.inject.Inject; import javax.inject.Named; @@ -43,6 +42,12 @@ import com.xwiki.licensing.LicensedExtensionManager; +/** + * Description in progress. + * + * @version $Id$ + * @since 1.27 + */ @Component @Named(LicenseRenewListener.NAME) @Singleton @@ -60,10 +65,7 @@ public class LicenseRenewListener implements EventListener private InstalledExtensionRepository installedExtensionRepository; @Inject - private TrialLicenseGenerator trialLicenseGenerator; - - @Inject - private LicenseRenew licenseRenew; + private DefaultLicenseUpdater licenseUpdater; @Override public List getEvents() @@ -77,46 +79,47 @@ public String getName() return NAME; } - @SuppressWarnings("unchecked") @Override public void onEvent(Event event, Object source, Object data) { - // Retrieve license updates. This method will be moved to another component. - trialLicenseGenerator.updateLicenses(); + // Retrieve license updates from store. + licenseUpdater.getLicensesUpdates(); ExtensionEvent extensionEvent = (ExtensionEvent) event; if (licensedExtensionManager.getLicensedExtensions().contains(extensionEvent.getExtensionId())) { - // Handle the new extension version. InstalledExtension installedExtension = (InstalledExtension) source; if (installedExtension == null) { return; } - Set newLicensedDependencies = new HashSet<>(); - Stack dependencyPath = new Stack<>(); - licenseRenew.getLicensedDependencies(newLicensedDependencies, dependencyPath, installedExtension, - extensionEvent.getNamespace()); - System.out.println(newLicensedDependencies); - - // Handle the old extension version. - if (data == null) { - return; - } - for (InstalledExtension oldExtension : (Collection) data) { - if (oldExtension.getId().getId().equals(installedExtension.getId().getId())) { - Set oldLicensedDependencies = new HashSet<>(); - dependencyPath = new Stack<>(); - licenseRenew.getLicensedDependencies(oldLicensedDependencies, dependencyPath, oldExtension, - extensionEvent.getNamespace()); - System.out.println(oldLicensedDependencies); - - // In progress: ! removed for testing purposes. - if (newLicensedDependencies.equals(oldLicensedDependencies)) { - licenseRenew.renewLicense(installedExtension.getId()); - } - } + Set licensedDependencies = + licensedExtensionManager.getLicensedDependencies(installedExtension, extensionEvent.getNamespace()); + System.out.println(licensedDependencies); + + Set previousDependencies = + getPreviousDependencies(data, installedExtension, extensionEvent.getNamespace()); + System.out.println(previousDependencies); + + // In progress: ! removed for testing purposes. + if (licensedDependencies.equals(previousDependencies)) { + licenseUpdater.renewLicense(installedExtension.getId()); } } } + @SuppressWarnings("unchecked") + private Set getPreviousDependencies(Object data, InstalledExtension installedExtension, + String namespace) + { + if (data == null) { + return new HashSet<>(); + } + + for (InstalledExtension previousInstalledExtension : (Collection) data) { + if (previousInstalledExtension.getId().getId().equals(installedExtension.getId().getId())) { + return licensedExtensionManager.getLicensedDependencies(previousInstalledExtension, namespace); + } + } + return new HashSet<>(); + } } diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/TrialLicenseGenerator.java b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/TrialLicenseGenerator.java index 8a0b8ed..1f1ee4a 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/TrialLicenseGenerator.java +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/TrialLicenseGenerator.java @@ -19,14 +19,9 @@ */ package com.xwiki.licensing.internal; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; import java.net.URL; -import java.util.List; import javax.inject.Inject; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; @@ -35,15 +30,11 @@ import org.apache.http.client.utils.URIBuilder; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; -import org.xwiki.crypto.BinaryStringEncoder; import org.xwiki.extension.ExtensionId; import org.xwiki.instance.InstanceIdManager; -import org.xwiki.properties.converter.Converter; -import com.fasterxml.jackson.databind.ObjectMapper; import com.xpn.xwiki.XWikiContext; import com.xwiki.licensing.License; -import com.xwiki.licensing.LicenseManager; import com.xwiki.licensing.LicensedExtensionManager; import com.xwiki.licensing.LicensingConfiguration; import com.xwiki.licensing.Licensor; @@ -81,17 +72,10 @@ public class TrialLicenseGenerator private Provider licensorProvider; @Inject - private Provider licenseManagerProvider; - - @Inject - @Named("Base64") - private BinaryStringEncoder base64decoder; + private Provider contextProvider; @Inject - private Converter converter; - - @Inject - private Provider contextProvider; + private DefaultLicenseUpdater licenseUpdater; /** * Generate trial license for the given extension. @@ -115,7 +99,7 @@ public void generateTrialLicense(ExtensionId extensionId) logger.debug("Failed to generate trial license for [{}] on store.", extensionId.getId()); } else { logger.debug("Trial license added for [{}]", extensionId.getId()); - updateLicenses(); + licenseUpdater.getLicensesUpdates(); } } catch (Exception e) { logger.warn("Failed to get trial license for [{}]. Root cause is [{}]", extensionId, @@ -165,69 +149,6 @@ private URL getTrialURL(ExtensionId extensionId) throws Exception return builder.build().toURL(); } - /** - * Retrieve license updates from the XWiki Store. In progress: move it to another component. - */ - @SuppressWarnings("unchecked") - public void updateLicenses() - { - try { - URL licensesUpdateURL = getLicensesUpdateURL(); - if (licensesUpdateURL == null) { - logger.debug("Failed to update licenses because the licensor configuration is not complete. " - + "Check your store update URL."); - return; - } - - XWikiContext xcontext = contextProvider.get(); - String licensesUpdateResponse = xcontext.getWiki().getURLContent(licensesUpdateURL.toString(), xcontext); - ObjectMapper objectMapper = new ObjectMapper(); - - List retrivedLicenses = (List) objectMapper.readValue(licensesUpdateResponse, Object.class); - for (String license : retrivedLicenses) { - License retrivedLicense = converter.convert(License.class, base64decoder.decode(license)); - if (retrivedLicense != null) { - licenseManagerProvider.get().add(retrivedLicense); - } - } - } catch (URISyntaxException | IOException e) { - logger.warn("Error while updating licenses. Root cause [{}]", ExceptionUtils.getRootCauseMessage(e)); - } - - } - - /** - * Construct the URL for updating licenses. - * - * @return the URL for updating licenses, or null if it cannot be constructed - * @throws URISyntaxException if the URL is not valid - * @throws MalformedURLException if an error occurred while constructing the URL - */ - private URL getLicensesUpdateURL() throws URISyntaxException, MalformedURLException - { - String storeUpdateURL = licensingConfig.getStoreUpdateURL(); - // In case the property has no filled value, the URL cannot be constructed. - if (storeUpdateURL == null) { - return null; - } - - URIBuilder builder = new URIBuilder(storeUpdateURL); - builder.addParameter(INSTANCE_ID, instanceIdManagerProvider.get().getInstanceId().toString()); - builder.addParameter("outputSyntax", "plain"); - - for (ExtensionId paidExtensionId : licensedExtensionManager.getMandatoryLicensedExtensions()) { - builder.addParameter(FEATURE_ID, paidExtensionId.getId()); - - License license = licensorProvider.get().getLicense(paidExtensionId); - if (license != null && !License.UNLICENSED.equals(license)) { - builder.addParameter(String.format("expirationDate:%s", paidExtensionId.getId()), - Long.toString(license.getExpirationDate())); - } - } - URL updateURL = builder.build().toURL(); - return updateURL; - } - /** * Check if for the given licensed extension a license is mandatory, meaning that it is not covered by the license * of other extension (it's not dependency of other licensed extension). diff --git a/application-licensing-licensor/application-licensing-licensor-api/src/main/resources/META-INF/components.txt b/application-licensing-licensor/application-licensing-licensor-api/src/main/resources/META-INF/components.txt index c760a4a..9257f22 100644 --- a/application-licensing-licensor/application-licensing-licensor-api/src/main/resources/META-INF/components.txt +++ b/application-licensing-licensor/application-licensing-licensor-api/src/main/resources/META-INF/components.txt @@ -10,6 +10,7 @@ com.xwiki.licensing.internal.DefaultLicenseValidator com.xwiki.licensing.internal.DefaultLicensingConfiguration com.xwiki.licensing.internal.LicenseManagerEventListener com.xwiki.licensing.internal.LicenseRenewListener +com.xwiki.licensing.internal.DefaultLicenseUpdater com.xwiki.licensing.internal.UserCounter com.xwiki.licensing.internal.UserCounter$UserListener com.xwiki.licensing.script.LicensorScriptService