/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.humantask.core.store.repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.humantask.core.HumanTaskConstants;
import org.wso2.carbon.humantask.core.dao.DeploymentUnitDAO;
import org.wso2.carbon.humantask.core.deployment.HumanTaskDeploymentUnit;
import org.wso2.carbon.humantask.core.store.HumanTaskStoreException;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.utils.RegistryClientUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* HumanTask Package Repository is responsible for managing registry based human task deployment units
* HumanTask Packages will be stored in the registry as follows.
* <p/>
* <HumanTask_ROOT>/<HumanTask_PACKAGE_NAME>
* |
* + prop_humantask.package.latest.version
* + prop_humantask.package.status
* + prop_humantask.package.latest.checksum
* + versions
* |
* +<HumanTask_PACKAGE_NAME-version1>
* +<HumanTask_PACKAGE_NAME-version2>
* +<HumanTask_PACKAGE_NAME-version3>
*/
public class HumanTaskPackageRepository {
private static Log log = LogFactory.getLog(HumanTaskPackageRepository.class);
// Config registry instance use to store human task package information for this repository instance.
private Registry configRegistry;
// Location of local file system where we keep human task archives.
private File humanTaskArchiveRepo;
public HumanTaskPackageRepository(Registry configRegistry, File humanTaskArchiveRepo) {
this.configRegistry = configRegistry;
this.humanTaskArchiveRepo = humanTaskArchiveRepo;
}
/**
* Handles deployment of new human task packages. Stores all the meta data and human task Package content
* in the registry.
* Update the registry meta data on human task package if package already exists.
*
* @param humanTaskDeploymentUnit containing information about current deployment
* @throws Exception on registry access error.
*/
public void handleNewHumanTaskPackageAddition(HumanTaskDeploymentUnit humanTaskDeploymentUnit, File humanTaskFile)
throws Exception {
try {
if (!isDUCollectionIsThere(humanTaskDeploymentUnit)) {
configRegistry.beginTransaction();
createOrUpdateHumanTaskPackageParentCollectionWithProperties(humanTaskDeploymentUnit);
addLatestArchiveToRegistryCollection(humanTaskDeploymentUnit, humanTaskFile);
createCollectionWithHumanTaskPackageContentForCurrentVersion(humanTaskDeploymentUnit);
configRegistry.commitTransaction();
}
} catch (RegistryException re) {
handleExceptionWithRollback("Unable to handle new HumanTask Package addition."
+ " Package: " + humanTaskDeploymentUnit.getPackageName(), re);
}
}
/**
* Restore the extracted human task package file from file system
*
* @param deploymentUnitDAO
* @throws Exception on registry access error.
*/
public void restoreHumanTaskPackageContentInRegistry(DeploymentUnitDAO deploymentUnitDAO, File humanTaskFile)
throws Exception {
try {
if (!isDUCollectionIsThere(deploymentUnitDAO)) {
String packageLocation = HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackage
(deploymentUnitDAO);
configRegistry.beginTransaction();
if (!configRegistry.resourceExists(packageLocation)) {
createHumanTaskPackageParentCollectionWithProperties(deploymentUnitDAO);
addLatestArchiveToRegistryCollection(deploymentUnitDAO, humanTaskFile);
}
createCollectionWithHumanTaskPackageContentForCurrentVersion(deploymentUnitDAO);
configRegistry.commitTransaction();
}
} catch (RegistryException re) {
handleExceptionWithRollback("Unable to handle new HumanTask Package addition."
+ " Package: " + deploymentUnitDAO.getPackageName(), re);
}
}
/**
* Check whether collection for human task package is exist in the registry
*
* @param humanTaskDeploymentUnit
* @throws RegistryException
*/
private boolean isDUCollectionIsThere(HumanTaskDeploymentUnit humanTaskDeploymentUnit)
throws RegistryException {
String collectionLocation = HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackageContent
(humanTaskDeploymentUnit);
return configRegistry.resourceExists(collectionLocation);
}
/**
* Check whether collection for human task package is exist in the registry
*
* @param deploymentUnitDAO
* @throws RegistryException
*/
private boolean isDUCollectionIsThere(DeploymentUnitDAO deploymentUnitDAO)
throws RegistryException {
String collectionLocation = HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackageContent
(deploymentUnitDAO);
return configRegistry.resourceExists(collectionLocation);
}
/**
* If registry contain the collection for human task package then package properties will get update
* If not new collection will be created for human task package.
*
* @param humanTaskDeploymentUnit
* @throws RegistryException
*/
private void createOrUpdateHumanTaskPackageParentCollectionWithProperties(
HumanTaskDeploymentUnit humanTaskDeploymentUnit) throws RegistryException {
String packageLocation = HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackage
(humanTaskDeploymentUnit);
if (configRegistry.resourceExists(packageLocation)) {
updateHumanTaskPackageProperties(humanTaskDeploymentUnit);
} else {
createHumanTaskPackageParentCollectionWithProperties(humanTaskDeploymentUnit);
}
}
/**
* Create parent collection to persisting human task package information. For example, if you deploy
* a human task archive called 'ClaimsApprovalTask.zip', we store information of that package in collection
* named 'ClaimsApprovalTask'. This will be the root for 'ClaimsApprovalTask' human task package information and
* there will several versions of this human task package in this registry collection which relates
* to the versions deployed in human task engine.
*
* @param humanTaskDeploymentUnit containing information on current deployment
* @throws RegistryException when there is a error accessing registry
*/
private void createHumanTaskPackageParentCollectionWithProperties(HumanTaskDeploymentUnit humanTaskDeploymentUnit)
throws RegistryException {
Collection humanPackage = configRegistry.newCollection();
humanPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_LATEST_CHECKSUM, humanTaskDeploymentUnit
.getMd5sum());
if (log.isDebugEnabled()) {
log.debug(humanTaskDeploymentUnit.getPackageName() + " updating checksum: " + humanTaskDeploymentUnit
.getMd5sum() + " in registry");
}
humanPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_STATUS, String.valueOf
(humanTaskDeploymentUnit.getTaskPackageStatus()));
humanPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_LATEST_VERSION,
Long.toString(humanTaskDeploymentUnit.getVersion()));
configRegistry.put(HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackage
(humanTaskDeploymentUnit), humanPackage);
}
/**
* Create parent collection for human task package using DeploymentUnitDAO
*
* @param deploymentUnitDAO
* @throws RegistryException
*/
private void createHumanTaskPackageParentCollectionWithProperties(DeploymentUnitDAO deploymentUnitDAO)
throws RegistryException {
Collection humanPackage = configRegistry.newCollection();
humanPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_LATEST_CHECKSUM, deploymentUnitDAO
.getChecksum());
if (log.isDebugEnabled()) {
log.debug(deploymentUnitDAO.getPackageName() + " updating checksum: " + deploymentUnitDAO
.getChecksum() + " in registry");
}
humanPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_STATUS, String.valueOf
(deploymentUnitDAO.getStatus()));
humanPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_LATEST_VERSION,
Long.toString(deploymentUnitDAO.getVersion()));
configRegistry.put(HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackage
(deploymentUnitDAO), humanPackage);
}
/**
* Update the properties of existing human task package in the registry
*
* @param humanTaskDeploymentUnit
* @throws RegistryException
*/
private void updateHumanTaskPackageProperties(HumanTaskDeploymentUnit humanTaskDeploymentUnit)
throws RegistryException {
String packageLocation =
HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackage(humanTaskDeploymentUnit);
Resource humanTaskPackage = configRegistry.get(packageLocation);
humanTaskPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_LATEST_CHECKSUM,
humanTaskDeploymentUnit.getMd5sum());
if (log.isDebugEnabled()) {
log.debug(humanTaskDeploymentUnit.getPackageName() + " updated checksum to: " +
humanTaskDeploymentUnit.getMd5sum());
}
humanTaskPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_STATUS,
String.valueOf(humanTaskDeploymentUnit.getTaskPackageStatus()));
humanTaskPackage.setProperty(HumanTaskConstants.HUMANTASK_PACKAGE_PROP_LATEST_VERSION,
Long.toString(humanTaskDeploymentUnit.getVersion()));
configRegistry.put(packageLocation, humanTaskPackage);
}
/**
* Add latest human task package zip to the registry
*
* @param humanTaskDeploymentUnit
* @param humanTaskFile
* @throws HumanTaskStoreException
* @throws RegistryException
*/
private void addLatestArchiveToRegistryCollection(HumanTaskDeploymentUnit humanTaskDeploymentUnit,
File humanTaskFile)
throws HumanTaskStoreException, RegistryException {
FileInputStream fileInputStream = null;
try {
Resource latestHumanTaskArchive = configRegistry.newResource();
fileInputStream = new FileInputStream(humanTaskFile);
latestHumanTaskArchive.setContent(fileInputStream);
configRegistry.put(HumanTaskPackageRepositoryUtils.getHumanTaskPackageArchiveResourcePath
(humanTaskDeploymentUnit.getPackageName()), latestHumanTaskArchive);
} catch (FileNotFoundException ex) {
String errMsg = "HumanTask package zip file couldn't found on given location " +
humanTaskFile.getAbsolutePath();
throw new HumanTaskStoreException(errMsg, ex);
} catch (RegistryException ex) {
String errMsg = "Exception occurred while adding latest archive to registry collection";
throw new RegistryException(errMsg, ex);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
log.warn("Cannot close file input stream.", e);
}
}
}
}
/**
* Add latest human task package zip to the registry
*
* @param deploymentUnitDAO
* @param humanTaskFile
* @throws RegistryException
* @throws HumanTaskStoreException
*/
private void addLatestArchiveToRegistryCollection(DeploymentUnitDAO deploymentUnitDAO,
File humanTaskFile)
throws HumanTaskStoreException, RegistryException {
FileInputStream fileInputStream = null;
try {
Resource latestHumanTaskArchive = configRegistry.newResource();
fileInputStream = new FileInputStream(humanTaskFile);
latestHumanTaskArchive.setContent(fileInputStream);
configRegistry.put(HumanTaskPackageRepositoryUtils.getHumanTaskPackageArchiveResourcePath
(deploymentUnitDAO.getPackageName()), latestHumanTaskArchive);
} catch (FileNotFoundException ex) {
String errMsg = "HumanTask package zip file couldn't found on given location " +
humanTaskFile.getAbsolutePath();
throw new HumanTaskStoreException(errMsg, ex);
} catch (RegistryException ex) {
String errMsg = "Exception occurred while adding latest archive to registry collection";
throw new RegistryException(errMsg, ex);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
log.warn("Cannot close file input stream.", e);
}
}
}
}
/**
* This repository persist extracted human task package content inside the human task Package collection
* under the child collection 'versions'. The collection name is same as directory with version
* attached to it's name(Example: ClaimsApprovalTask-3).
* <p/>
* For the 'ClaimsApprovalTask' human task package, extracted human task package will be stored in a registry
* location like '<config_registry_root>/humantask/packages/ClaimsApprovalTask/versions/ClaimsApprovalTask-3'.
*
* @param humanTaskDeploymentUnit containing information on current human task deployment.
* @throws RegistryException if an error occurred during import of file system content to
* registry.
*/
private void createCollectionWithHumanTaskPackageContentForCurrentVersion(
HumanTaskDeploymentUnit humanTaskDeploymentUnit) throws RegistryException {
String collectionLocation =
HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackageVersions(humanTaskDeploymentUnit);
RegistryClientUtils.importToRegistry(new File(humanTaskArchiveRepo + File.separator +
humanTaskDeploymentUnit.getName()), collectionLocation,
configRegistry);
}
/**
* This repository persist extracted human task package content inside the human task Package collection
* under the child collection 'versions'.
*
* @param deploymentUnitDAO
* @throws RegistryException
*/
private void createCollectionWithHumanTaskPackageContentForCurrentVersion(
DeploymentUnitDAO deploymentUnitDAO) throws RegistryException {
String collectionLocation =
HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackageVersions(deploymentUnitDAO);
RegistryClientUtils.importToRegistry(new File(humanTaskArchiveRepo + File.separator +
deploymentUnitDAO.getName()), collectionLocation,
configRegistry);
}
/**
* Un-deploy the human task package from registry
*
* @param packageName
* @throws RegistryException
*/
public void handleHumanTaskPackageUndeploy(String packageName) throws RegistryException {
try {
String packageLocation =
HumanTaskPackageRepositoryUtils.getResourcePathForHumanTaskPackage(packageName);
if (!configRegistry.getRegistryContext().isReadOnly() && configRegistry.resourceExists(packageLocation)) {
configRegistry.delete(packageLocation);
}
} catch (RegistryException re) {
String errMessage = "Unable to access registry for handling HumanTask package undeployment."
+ " Package: " + packageName;
log.error(errMessage, re);
throw re;
}
}
/**
* Handles exception and rollbacks an already started transaction. Don't use this method if
* you haven't already started a registry transaction
*
* @param msg - Message to log
* @param e - original exception
* @throws RegistryException on registry rollback error case, we'll init the cause to the
* original exception we got when accessing registry
*/
protected void handleExceptionWithRollback(String msg, Exception e)
throws Exception {
Exception cachedException = null;
log.error(msg, e);
try {
configRegistry.rollbackTransaction();
} catch (RegistryException re) {
cachedException = re;
log.error("Transaction rollback failed", re);
}
if (cachedException != null) {
cachedException.initCause(e);
throw cachedException;
} else {
throw e;
}
}
}