ProductInformations.java
/**
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.commons.info;
import org.exoplatform.commons.api.settings.SettingService;
import org.exoplatform.commons.api.settings.SettingValue;
import org.exoplatform.commons.api.settings.data.Context;
import org.exoplatform.commons.api.settings.data.Scope;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.app.SessionProviderService;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.settings.jpa.entity.SettingsEntity;
import org.picocontainer.Startable;
import javax.jcr.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:anouar.chattouna@exoplatform.com">Anouar
* Chattouna</a>
* @version $Revision$
*/
public class ProductInformations implements Startable {
public static final String product_Information = "ProductInformation";
public static final String ENTERPRISE_EDITION = "ENTERPRISE";
public static final String EXPRESS_EDITION = "EXPRESS";
public static final String EDITION = "edition";
public static final String KEY_GENERATION_DATE = "key generation date";
public static final String DELAY = "delay";
public static final String PRODUCT_CODE = "productCode";
public static final String PRODUCT_KEY = "productKey";
public static final String NB_USERS = "number of users";
public static final String PRODUCT_GROUP_ID = "product.groupId";
public static final String PRODUCT_REVISION = "product.revision";
public static final String PRODUCT_BUILD_NUMBER = "product.buildNumber";
public static final String WORKING_WORSPACE_NAME = "working.worspace.name";
public static final String PRODUCT_VERSIONS_DECLARATION_FILE = "product.versions.declaration.file";
/**
* Constant that will be used in nodeHierarchyCreator.getJcrPath: it represents
* the Application data root node Alias
*/
public static final String EXO_APPLICATIONS_DATA_NODE_ALIAS = "exoApplicationDataNode";
/**
* Service application data node name
*/
public static final String UPGRADE_PRODUCT_SERVICE_NODE_NAME = "ProductInformationsService";
/**
* node name where the Product version declaration is
*/
public static final String PRODUCT_VERSION_DECLARATION_NODE_NAME = "productVersionDeclarationNode";
private static final Log LOG = ExoLogger.getLogger(ProductInformations.class);
public String applicationDataRootNodePath = null;
private String productVersionDeclarationNodePath = null;
private String workspaceName = null;
private Properties productInformationProperties = new Properties();
private Map<String, String> productInformation = new HashMap<>();
private boolean firstRun = false;
private SettingService settingService;
private NodeHierarchyCreator nodeHierarchyCreator;
private RepositoryService repositoryService = null;
private SessionProviderService sessionProviderService = null;
public ProductInformations(ConfigurationManager cmanager,
NodeHierarchyCreator nodeHierarchyCreator,
InitParams initParams,
SettingService settingService,
SessionProviderService sessionProviderService,
RepositoryService repositoryService) {
this.repositoryService = repositoryService;
this.sessionProviderService = sessionProviderService;
this.settingService = settingService;
this.nodeHierarchyCreator = nodeHierarchyCreator;
if (!initParams.containsKey(PRODUCT_VERSIONS_DECLARATION_FILE)) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't find the init value param: " + PRODUCT_VERSIONS_DECLARATION_FILE);
}
return;
}
String filePath = initParams.getValueParam(PRODUCT_VERSIONS_DECLARATION_FILE).getValue();
try {
if (LOG.isInfoEnabled()) {
LOG.info("Read products versions from " + filePath);
}
InputStream inputStream = cmanager.getInputStream(filePath);
productInformationProperties.load(inputStream);
} catch (IOException exception) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't parse the file " + filePath, exception);
}
return;
} catch (Exception exception) {
// ConfigurationManager.getInputStream() throws Exception().
// It's from another project and we cannot modify it. So we have to catch
// Exception
if (LOG.isErrorEnabled()) {
LOG.error("Error occured while reading the file " + filePath, exception);
}
return;
}
if (initParams.containsKey(WORKING_WORSPACE_NAME)) {
workspaceName = initParams.getValueParam(WORKING_WORSPACE_NAME).getValue();
}
}
public String getEdition() throws MissingProductInformationException {
return productInformation.get(EDITION);
}
public String getNumberOfUsers() throws MissingProductInformationException {
return productInformation.get(NB_USERS);
}
public String getDateOfLicence() throws MissingProductInformationException {
return productInformation.get(KEY_GENERATION_DATE);
}
public String getDuration() throws MissingProductInformationException {
return productInformation.get(DELAY);
}
public String getProductCode() throws MissingProductInformationException {
return productInformation.get(PRODUCT_CODE);
}
public String getProductKey() throws MissingProductInformationException {
return productInformation.get(PRODUCT_KEY);
}
/**
* @return This method returns the current product's version.
*/
public String getVersion() throws MissingProductInformationException {
return getVersion(getCurrentProductGroupId());
}
/**
* @return This method return the product version, selected by its maven
* groupId.
*/
public String getVersion(String productGroupId) throws MissingProductInformationException {
if (!productInformationProperties.containsKey(productGroupId)) {
throw new MissingProductInformationException(productGroupId);
}
return productInformationProperties.getProperty(productGroupId);
}
/**
* @return the product.buildNumber property value.
*/
public String getBuildNumber() throws MissingProductInformationException {
if (!productInformationProperties.containsKey(PRODUCT_BUILD_NUMBER)) {
throw new MissingProductInformationException(PRODUCT_BUILD_NUMBER);
}
return productInformationProperties.getProperty(PRODUCT_BUILD_NUMBER);
}
/**
* @return the product.revision property value.
*/
public String getRevision() throws MissingProductInformationException {
if (!productInformationProperties.containsKey(PRODUCT_REVISION)) {
throw new MissingProductInformationException(PRODUCT_REVISION);
}
return productInformationProperties.getProperty(PRODUCT_REVISION);
}
/**
* @return the current product's maven group id.
*/
public String getCurrentProductGroupId() throws MissingProductInformationException {
if (!productInformationProperties.containsKey(PRODUCT_GROUP_ID)) {
throw new MissingProductInformationException(PRODUCT_GROUP_ID);
}
return productInformationProperties.getProperty(PRODUCT_GROUP_ID);
}
/**
* @return the platform.version property. This method return the platform
* version.
*/
public String getPreviousVersion() throws MissingProductInformationException {
return getPreviousVersion(getCurrentProductGroupId());
}
/**
* @return the platform.version property. This method return the platform
* version.
*/
public String getPreviousVersion(String productGroupId) throws MissingProductInformationException {
if (!productInformation.containsKey(productGroupId)) {
throw new MissingProductInformationException(productGroupId);
}
return productInformation.get(productGroupId);
}
/**
* @return an empty string if the properties file is not found, otherwise the
* platform.buildNumber property. This method return the build number of
* the platform.
*/
public String getPreviousBuildNumber() throws MissingProductInformationException {
if (!productInformation.containsKey(PRODUCT_BUILD_NUMBER)) {
throw new MissingProductInformationException(PRODUCT_BUILD_NUMBER);
}
return productInformation.get(PRODUCT_BUILD_NUMBER);
}
/**
* @return the value of product.revision property. This method return the
* current revison of the platform.
*/
public String getPreviousRevision() throws MissingProductInformationException {
if (!productInformation.containsKey(PRODUCT_REVISION)) {
throw new MissingProductInformationException(PRODUCT_REVISION);
}
return productInformation.get(PRODUCT_REVISION);
}
public boolean isFirstRun() {
return this.firstRun;
}
/**
* This method migrate from the JCR the stored products versions to JPA. If it's
* the first server start up, then store the declared one.
*/
public void start() {
try {
migrateProductInformation();
// Load product information from DB
Map<String, SettingValue> productInformationSettings =
settingService.getSettingsByContextAndScope(Context.GLOBAL.getName(),
Context.GLOBAL.getId(),
Scope.APPLICATION.getName(),
product_Information);
if (productInformationSettings != null && !productInformationSettings.isEmpty()) {
productInformationSettings.entrySet()
.stream()
.forEach(e -> productInformation.put(e.getKey(), e.getValue().getValue().toString()));
} else {// This is the first time that this Service starts up
LOG.info("Platform first run - init and store product Information");
firstRun = true;
// Store product information properties in DB
initProductInformation(productInformationProperties);
storeProductInformation(productInformation);
}
} catch (Exception e) {
LOG.error("Error while starting product information service - Cause : " + e.getMessage(), e);
}
}
/**
* This method is called by eXo Kernel when stopping the parent ExoContainer
*/
public void stop() {
}
public void storeProductInformation(Map<String, String> map) {
try {
for (Map.Entry<String, String> entry : map.entrySet()) {
settingService.set(Context.GLOBAL,
Scope.APPLICATION.id(product_Information),
entry.getKey(),
SettingValue.create(entry.getValue()));
}
} catch (Exception e) {
LOG.error("Error while storing product informations - Cause : " + e.getMessage(), e);
}
}
public void initProductInformation(Properties properties) {
properties.entrySet().stream().forEach(entry -> productInformation.put((String) entry.getKey(), (String) entry.getValue()));
}
/**
* Migrate product information from JCR to RDBMS
*/
public void migrateProductInformation() {
if (workspaceName == null || workspaceName.equals("")) {
try {
workspaceName = repositoryService.getCurrentRepository().getConfiguration().getDefaultWorkspaceName();
if (LOG.isInfoEnabled()) {
LOG.info("Workspace wasn't specified, use '" + workspaceName + "' as default workspace of this repository.");
}
} catch (RepositoryException exception) {
LOG.error("Error occured while getting default workspace name.", exception);
return;
}
}
Session session = null;
try {
session = getSession();
applicationDataRootNodePath = nodeHierarchyCreator.getJcrPath(EXO_APPLICATIONS_DATA_NODE_ALIAS);
productVersionDeclarationNodePath = applicationDataRootNodePath + "/" + UPGRADE_PRODUCT_SERVICE_NODE_NAME + "/"
+ PRODUCT_VERSION_DECLARATION_NODE_NAME;
if (session.itemExists(productVersionDeclarationNodePath)) {
Node productVersionDeclarationNode = (Node) session.getItem(productVersionDeclarationNodePath);
Node productVersionDeclarationNodeContent = productVersionDeclarationNode.getNode("jcr:content");
String data = productVersionDeclarationNodeContent.getProperty("jcr:data").getString();
Properties jcrInformation = new Properties();
jcrInformation.load(new ByteArrayInputStream(data.getBytes()));
initProductInformation(jcrInformation);
storeProductInformation(productInformation);
productVersionDeclarationNode.getParent().remove();
LOG.info("productVersionDeclaration node removed!");
session.save();
} else {
LOG.info("No product information to migrate from JCR to RDBMS");
}
} catch (LoginException exception) {
LOG.error("Can't load product informations from the JCR: Error when getting JCR session.", exception);
return;
} catch (NoSuchWorkspaceException exception) {
LOG.error("Can't load product informations from the JCR: Error when getting JCR session.", exception);
return;
} catch (RepositoryException exception) {
LOG.error("Can't load product informations from the JCR!", exception);
return;
} catch (IOException exception) {
LOG.error("Can't load product informations from the JCR: the data stored in the JCR couldn't be parsed.", exception);
return;
}
finally {
if (session != null) {
session.logout();
}
}
}
public void setUnlockInformation(Properties unlockInformation) {
productInformation.put(EDITION, (String) unlockInformation.get(EDITION));
productInformation.put(NB_USERS, (String) unlockInformation.get(NB_USERS));
productInformation.put(PRODUCT_KEY, (String) unlockInformation.get(PRODUCT_KEY));
productInformation.put(PRODUCT_CODE, (String) unlockInformation.get(PRODUCT_CODE));
productInformation.put(DELAY, (String) unlockInformation.get(DELAY));
productInformation.put(KEY_GENERATION_DATE, (String) unlockInformation.get(KEY_GENERATION_DATE));
}
public void setPreviousVersionsIfFirstRun(String defaultVersion) {
if (isFirstRun()) {
initProductInformation(productInformationProperties);
productInformation.forEach((key, value) -> productInformation.put(key, defaultVersion));
}
}
public String getWorkspaceName() {
return workspaceName;
}
public String getProductVersionDeclarationNodePath() {
return this.productVersionDeclarationNodePath;
}
private static String currentFlag() {
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
return dateFormat.format(Calendar.getInstance(TimeZone.getDefault()).getTime());
}
public void setProductInformationProperties(Properties productInformationProperties) {
this.productInformationProperties = productInformationProperties;
}
public Properties getProductInformationProperties() {
return productInformationProperties;
}
public Map<String, String> getProductInformation() {
return productInformation;
}
public void setFirstRun(boolean firstRun) {
this.firstRun = firstRun;
}
private Session getSession() throws RepositoryException, LoginException, NoSuchWorkspaceException {
SessionProvider sessionProvider = sessionProviderService.getSystemSessionProvider(null);
ManageableRepository repository = repositoryService.getCurrentRepository();
return sessionProvider.getSession(workspaceName, repository);
}
}