/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.license; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.DateFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Locale; import java.util.Properties; import java.util.TimeZone; import java.util.logging.Level; import com.rapidminer.RapidMiner; import com.rapidminer.RapidMiner.ExecutionMode; import com.rapidminer.core.license.ProductConstraintManager; import com.rapidminer.license.ConstraintNotRestrictedException; import com.rapidminer.license.License; import com.rapidminer.license.LicenseConstants; import com.rapidminer.tools.FileSystemService; import com.rapidminer.tools.I18N; import com.rapidminer.tools.LogService; /** * Collection of utility functions for license handling. * * @author Michael Knopf, Sabrina Kirstein */ public class LicenseTools { private static final String LICENSE_PROPERTIES_PATH = "license.properties"; private static final String LAST_ACTIVE_LICENSE_PRECEDENCE_FOR_PRODUCT = "license.last_active.%s.precedence"; private static final String LAST_ACTIVE_LICENSE_PRODUCT_EDITION_FOR_PRODUCT = "license.last_active.%s.product_edition"; private static final String LAST_ACTIVE_LICENSE_EXPIRATION_DATE_FOR_PRODUCT = "license.last_active.%s.expiration_date"; private static final String FREE_TIER_PREFIX = "free"; /** * @deprecated use {@link #getPrecedenceKey(License)} instead. */ @Deprecated public static final String LAST_ACTIVE_LICENSE_PRECEDENCE = "license.last_active.precedence"; /** * @deprecated use {@link #getEditionKey(License)} instead. */ @Deprecated public static final String LAST_ACTIVE_LICENSE_PRODUCT_EDITION = "license.last_active.product_edition"; /** * @deprecated use {@link #getEditionKey(License)}, {@link #getExpirationDateKey(License)} or * {@link #getPrecedenceKey(License)} instead. */ @Deprecated public static final String LAST_ACTIVE_LICENSE_PRODUCT_ID = "license.last_active.product_id"; /** * @deprecated use {@link #getExpirationDateKey(License)} instead. */ @Deprecated public static final String LAST_ACTIVE_LICENSE_EXPIRATION_DATE = "license.last_active.expiration_date"; /** * Date formatter to generate ISO8601 compliant string representations in UTC time. */ public static final ThreadLocal<DateFormat> ISO_DATE_FORMATTER = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmXXX", Locale.UK); format.setTimeZone(TimeZone.getTimeZone("UTC")); return format; } }; /** * Get the translated name of the product associated with the license. * * @param license * The {@link License}. * @return The translated product name. */ public static String translateProductName(License license) { return I18N.getMessage(I18N.getGUIBundle(), "gui.license." + license.getProductId() + ".label"); } /** * Get the translated edition of the product associated with the license. * * @param license * The {@link License}. * @return The translated product edition. */ public static String translateProductEdition(License license) { return I18N.getMessage(I18N.getGUIBundle(), "gui.license." + license.getProductId() + "." + license.getProductEdition() + ".label"); } /** * Translates the data row constraint with the license. * * @param license * The {@link License}. * @return The translated data row constraint. */ public static String translateDataRowConstraint(License license) { String limit; try { limit = license.getConstraints().getConstraintValue(ProductConstraintManager.INSTANCE.getDataRowConstraint()); try { limit = NumberFormat.getInstance().format(Integer.parseInt(limit)); } catch (NumberFormatException e) { // ignore } } catch (ConstraintNotRestrictedException e) { limit = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.unlimited.label"); } return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.data_row.label", limit); } /** * Translates the Hadoop node constraint with the license. * * @param license * The {@link License}. * @return The translated Hadoop node constraint. */ public static String translateHadoopNodeConstraint(License license) { String limit; try { limit = license.getConstraints().getConstraintValue(LicenseConstants.NODES_CONSTRAINT); try { int numLimit = Integer.parseInt(limit); if (numLimit == -1) { limit = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.unlimited.label"); } else { limit = NumberFormat.getInstance().format(numLimit); } } catch (NumberFormatException e) { // ignore } } catch (ConstraintNotRestrictedException e) { limit = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.unlimited.label"); } return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.hadoop_node.label", limit); } /** * Translates the pushdown operator constraint with the license. * * @param license * The {@link License}. * @return The translated pushdown operator constraint. */ public static String translatePushdownOperatorConstraint(License license) { Boolean rmOperatorsAllowed; try { rmOperatorsAllowed = Boolean .parseBoolean(license.getConstraints().getConstraintValue(LicenseConstants.RM_IN_HADOOP_CONSTRAINT)); } catch (ConstraintNotRestrictedException e) { rmOperatorsAllowed = true; } String value; if (rmOperatorsAllowed) { value = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.enabled.label"); } else { value = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.disabled.label"); } return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.pushdown_operator.label", value); } /** * Translates the logical processor constraint with the license. * * @param license * The {@link License}. * @return The translated logical processor constraint. */ public static String translateLogicalProcessorConstraint(License license) { String limit; try { limit = license.getConstraints() .getConstraintValue(ProductConstraintManager.INSTANCE.getLogicalProcessorConstraint()); } catch (ConstraintNotRestrictedException e) { limit = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.unlimited.label"); } return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.logical_processor.label", limit); } /** * Translates the memory constraint with the license. * * @param license * The {@link License}. * @return The translated memory constraint. */ public static String translateMemoryConstraint(License license) { String limit; try { limit = license.getConstraints() .getConstraintValue(ProductConstraintManager.INSTANCE.getMemoryLimitConstraint()); } catch (ConstraintNotRestrictedException e) { return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.unlimited_memory.label"); } return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.memory.label", limit); } /** * Translates the web service constraint with the license. * * @param license * The {@link License}. * @return The translated web service constraint. */ public static String translateWebServiceConstraint(License license) { String limit; try { limit = license.getConstraints() .getConstraintValue(ProductConstraintManager.INSTANCE.getWebServiceLimitConstraint()); try { limit = NumberFormat.getInstance().format(Integer.parseInt(limit)); } catch (NumberFormatException e) { // ignore } } catch (ConstraintNotRestrictedException e) { limit = I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.value.unlimited.label"); } return I18N.getMessage(I18N.getGUIBundle(), "gui.license.constraint.web_service.label", limit); } /** * Load last active license properties. */ public static Properties loadLastActiveLicenseProperties() { File licensePropertiesFile = FileSystemService.getUserConfigFile(LICENSE_PROPERTIES_PATH); Properties licenseProperties = new Properties(); // try to load properties from file if (licensePropertiesFile.exists()) { try (FileInputStream in = new FileInputStream(licensePropertiesFile)) { licenseProperties.load(in); handleLegacyProperties(licenseProperties); } catch (IOException e) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.license.RMLicenseManagerListener.loading_properties_failed", e); } } return licenseProperties; } private static void handleLegacyProperties(Properties licenseProperties) { String legacyProductId = licenseProperties.getProperty(LAST_ACTIVE_LICENSE_PRODUCT_ID); if (legacyProductId != null) { String legacyEdition = licenseProperties.getProperty(LAST_ACTIVE_LICENSE_PRODUCT_EDITION); String legacyExpiration = licenseProperties.getProperty(LAST_ACTIVE_LICENSE_EXPIRATION_DATE); String legacyPrecedence = licenseProperties.getProperty(LAST_ACTIVE_LICENSE_PRECEDENCE); if (legacyEdition != null) { licenseProperties.setProperty( String.format(LAST_ACTIVE_LICENSE_PRODUCT_EDITION_FOR_PRODUCT, legacyProductId), legacyEdition); } if (legacyExpiration != null) { licenseProperties.setProperty( String.format(LAST_ACTIVE_LICENSE_EXPIRATION_DATE_FOR_PRODUCT, legacyProductId), legacyExpiration); } if (legacyPrecedence != null) { licenseProperties.setProperty(String.format(LAST_ACTIVE_LICENSE_PRECEDENCE_FOR_PRODUCT, legacyProductId), legacyPrecedence); } } licenseProperties.remove(LAST_ACTIVE_LICENSE_PRODUCT_ID); licenseProperties.remove(LAST_ACTIVE_LICENSE_PRODUCT_EDITION); licenseProperties.remove(LAST_ACTIVE_LICENSE_EXPIRATION_DATE); licenseProperties.remove(LAST_ACTIVE_LICENSE_PRECEDENCE); } /** * Store active license properties. Requires RapidMiner to be running ad standalone GUI * application. */ public static void storeActiveLicenseProperties(License activeLicense) { // do nothing when RapidMiner is not executed as standalone GUI application if (RapidMiner.getExecutionMode() != ExecutionMode.UI) { return; } // load existing properties file File licensePropertiesFile = FileSystemService.getUserConfigFile(LICENSE_PROPERTIES_PATH); Properties licenseProperties = LicenseTools.loadLastActiveLicenseProperties(); // store properties necessary to identify the license licenseProperties.setProperty(getEditionKey(activeLicense), activeLicense.getProductEdition()); licenseProperties.setProperty(getPrecedenceKey(activeLicense), String.valueOf(activeLicense.getPrecedence())); if (activeLicense.getExpirationDate() != null) { String dateString = ISO_DATE_FORMATTER.get().format(activeLicense.getExpirationDate()); licenseProperties.setProperty(getExpirationDateKey(activeLicense), dateString); } else { licenseProperties.remove(getExpirationDateKey(activeLicense)); } // store properties try (FileOutputStream out = new FileOutputStream(licensePropertiesFile)) { licenseProperties.store(out, "RapidMiner Studio License Properties"); } catch (IOException e) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.license.RMLicenseManagerListener.storing_properties_failed", e); } } public static String getPrecedenceKey(License license) { return String.format(LAST_ACTIVE_LICENSE_PRECEDENCE_FOR_PRODUCT, license.getProductId()); } public static String getExpirationDateKey(License license) { return String.format(LAST_ACTIVE_LICENSE_EXPIRATION_DATE_FOR_PRODUCT, license.getProductId()); } public static String getEditionKey(License license) { return String.format(LAST_ACTIVE_LICENSE_PRODUCT_EDITION_FOR_PRODUCT, license.getProductId()); } public static boolean isLicenseFree(License license) { return isLicenseFree(license.getProductEdition()); } public static boolean isLicenseFree(String edition) { // Compare the beginning of the edition String to the prefix of free tier licenses. return edition.startsWith(FREE_TIER_PREFIX); } }