package com.ibm.urbancode.zos.common
/*
 * Licensed Materials - Property of IBM Corp.
 * IBM UrbanCode Build
 * IBM UrbanCode Deploy
 * IBM UrbanCode Release
 * IBM AnthillPro
 * (c) Copyright IBM Corporation 2002, 2014. All Rights Reserved.
 *
 * U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
 * GSA ADP Schedule Contract with IBM Corp.
 */

import com.ibm.jzos.ZFile
import com.ibm.jzos.ZFileException

class DeploymentHelper {
    def static final filesCanBeDeletedFromWorkDir = new HashSet();
    static{
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.PACKAGE_MANIFEST_FILE_NAME);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.ROLLBACK_MANIFEST_FILE_NAME);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.DEPLOY_DELTA_FILE_NAME);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.DEPLOY_BACKUP_FILE_NAME);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.CONTAINER_MAPPER_FILE_NAME);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.CHECK_ACCESS_DS_FILE_NAME_BACKUP);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.CHECK_ACCESS_DS_FILE_NAME);
        filesCanBeDeletedFromWorkDir.add(DeploymentConstants.PACKAGE_FILE_NAME);
    }

    static getStringInput(input) {
        return input?.trim();
    }

    static getBooleanInput(input) {
        return Boolean.valueOf(input?.trim());
    }

    //Repository path not located in the component name folder, we need to add this folder on the path
    static getVersionDirPathInRepository(basePath, componentName, versionName){
        def repobasePathToVersion = basePath + File.separator + componentName + File.separator + versionName;
        return(repobasePathToVersion);
    }

    static getFilePathInRepository(basePath, componentName, versionName, fileName) {
        def patToFileInRepo = getVersionDirPathInRepository(basePath,componentName,versionName) + File.separator + fileName;
        return(patToFileInRepo);
    }

    //compatible=true, the return path will first check if <basepath>/deploy/component/version exists. and then the new path since v18
    //compatible=false, the return path will return the new path since v18, which is <basepath>/deploy/resourceId/component/version
    static getVersionPathInDeployBasePath(basePath, resourceId, componentName, versionName, compatible){
        def basePathToVersion = basePath + File.separator +
                DeploymentConstants.ADDITIONAL_FOLDER_FOR_BASE_PATH + File.separator +
                resourceId + File.separator +
                componentName + File.separator +
                versionName;

        if (compatible && !directoryExist(basePathToVersion)) {
            basePathToVersion = basePath + File.separator +
                DeploymentConstants.ADDITIONAL_FOLDER_FOR_BASE_PATH + File.separator +
                componentName + File.separator +
                versionName;
        }

        return(basePathToVersion);
    }

    static getComponentPathInDeployBasePath(basePath, resourceId, componentName, compatible){
        def basePathToComponent = basePath + File.separator +
                DeploymentConstants.ADDITIONAL_FOLDER_FOR_BASE_PATH + File.separator +
                resourceId + File.separator +
                componentName

        if (compatible && !directoryExist(basePathToComponent)) {
            basePathToComponent = basePath + File.separator +
                DeploymentConstants.ADDITIONAL_FOLDER_FOR_BASE_PATH + File.separator +
                componentName;
        }

        return(basePathToComponent);
    }

    static getFilePathInDeployBasePath(versionPathInBasePah, fileName) {
        def patToFileInBasePath = versionPathInBasePah + File.separator + fileName;
        return(patToFileInBasePath);
    }

    //Working copy default path is located in the component folder
    static getVersionDirPathInWorkingDir(basePath, versionname, resourceId){
        return(basePath + File.separator + resourceId + File.separator + versionname);
    }

    static getFilePathInWorkingDir(basePath, versionname, resourceId, fileName){
        def pathToFileInWorkDir = getVersionDirPathInWorkingDir(basePath, versionname, resourceId) + File.separator + fileName
        return(pathToFileInWorkDir);
    }

    static getPath4ExecScriptInToolkit(toolkitHome, execName){
        return(toolkitHome + File.separator + DeploymentConstants.ZOS_TOOLKIT_EXEC_FOLDER_NAME + File.separator + execName);
    }

    //Get ant script,will depends on our pacakge structure
    static getAntScriptFolderPath(){
        final def pluginHome = System.getenv("PLUGIN_HOME");
        return(pluginHome + File.separator + "scripts" + File.separator + "deployment");
    }

    //Validation methods
    static validateFileExist(filePath, errorInfo){
        def file = new File(filePath);
        if( !(file.exists() && file.isFile()) ){
            throw new IllegalArgumentException(errorInfo);
        }
    }

    static validateDirectoryExist(filePath, errorInfo){
        def file = new File(filePath);
        if( !(file.exists() && file.isDirectory()) ){
            throw new IllegalArgumentException(errorInfo);
        }
    }

    static directoryExist(directoryPath){
        def file = new File(directoryPath);
        if(file.exists() && file.isDirectory()){
            return(true);
        }

        return(false);
    }

    static fileExists(filePath){
        def fileExist = false;
        def file = new File(filePath);
        if( file.exists() && file.isFile() ){
            fileExist = true;
        }

        return(fileExist);
    }

    //Handle user's input rule mapping pair
    static handleMappingRule(pdsMapping, Map src2TargetMap, Map wildcardSrc2TargetMap) {
        if(pdsMapping && pdsMapping.size() > 0){
            def pdsMappingStr = "";
            pdsMappingStr = pdsMapping.trim();
            pdsMappingStr.replaceAll(DeploymentConstants.SYSTEM_LINE_SEPARATOR, DeploymentConstants.SRC_TO_TARGET_DELIMETER);
            def pdsMappingPairs = pdsMappingStr.split(DeploymentConstants.SRC_TO_TARGET_DELIMETER);
            pdsMappingPairs.each {pair->
                pair = pair.trim();
                if(pair.length() > 0){//Allow empty line which will be ignore
                    def onePair = pair.split(DeploymentConstants.MAPPING_RULER_DELIMETER);
                    onePair = onePair*.trim();
                    if(onePair.size() == 2){
                        if(containsWildcardCharactor(onePair[0])) {
                            def wildcardExpressKey = getKeyRegularExpressPattern(onePair[0]);
                            if(!wildcardSrc2TargetMap.containsKey(wildcardExpressKey)){
                                wildcardSrc2TargetMap.put(wildcardExpressKey, onePair[1]);
                            }else{
                                println "Warning - The mapping rule ${onePair[0]}, ${onePair[1]} is ignored,which was already set by ${onePair[0]}, ${src2TargetMap[onePair[0]]}";
                            }
                        } else {
                            if(!src2TargetMap.containsKey(onePair[0])){
                                src2TargetMap.put(onePair[0], onePair[1]);
                            }else{
                                println "Warning - The mapping rule ${onePair[0]}, ${onePair[1]} is ignored,which was already set by ${onePair[0]}, ${src2TargetMap[onePair[0]]}";
                            }
                        }
                    }else{//abc,cc,dd or abc, or ,cc will be treat as illegal input
                        throw new IllegalArgumentException("The format of ${pair} PDS mapping field is not correctly!");
                    }
                }
            }
        }
    }

    //We just support "*" now
    static containsWildcardCharactor(str) {
        return(str.contains("*"));
    }

    //return an pattern which removed "." and change the "*" to ".*"
    static getKeyRegularExpressPattern(str) {
        def pattern = ~str.replaceAll(/\./, "\\.").replaceAll(/\*/, "\\.\\*");
        return(pattern);
    }
    //Check access

    static checkAccess4Input(Set targetDsSet, dsListFile4BackUpPath, checkAccessExePath) {
        def InputTargetVolumeMap = [:];
        targetDsSet.each { datasetName->
            def dsn = "'" + datasetName + "'";
            def exists = dsExist(dsn);
            try {
                def vols = ZFile.locateDSN(dsn);
                if(null == vols || vols.size()<1){
                    printProcessOutput("Warning - Input dataset ${dsn} is not found!")
                }else if( vols.size() > 1){
                }else{
                    InputTargetVolumeMap.put(datasetName, vols[0]);
                }
            }catch(Exception locateException){
                //Can't find the the dsn
            }
        }
        //Generate the datasetlist file to call native checkaccess for deploy
        new File(dsListFile4BackUpPath).withWriter('IBM-1047'){ out ->
            InputTargetVolumeMap.each {datasetName,volume->
                out.println("${DeploymentConstants.CHECK_ACCESS_DS_INPUT_LEADER} ${datasetName} ${volume}");
            }
        }
        //Call native script to get the access code
        callCheckAccess(checkAccessExePath, dsListFile4BackUpPath, "input")
    }

    static checkAccess4Output(Set targetDsSet, dsListFilePath, checkAccessExePath) {
        def OutPutTargetVolumeMap = [:];
        targetDsSet.each { datasetName->
            def dsn = "'" + datasetName + "'";
            def exists = dsExist(dsn);
            if(!exists){
                OutPutTargetVolumeMap.put(datasetName, "******");
            }else{
                def vols = null;
                try{
                    vols = ZFile.locateDSN(dsn);
                }catch(Exception locateException){
                    println "The volumn of ${dsn} was not found for OUTPUT!";
                }

                if(null == vols || vols.size()<1){
                    OutPutTargetVolumeMap.put(datasetName, "******");
                }else if( vols.size() > 1){
                }else{
                    OutPutTargetVolumeMap.put(datasetName, vols[0]);
                }
            }
        }
        //Generate the datasetlist file to call native checkaccess for deploy
        new File(dsListFilePath).withWriter('IBM-1047'){ out ->
            OutPutTargetVolumeMap.each {datasetName,volume->
                out.println("${DeploymentConstants.CHECK_ACCESS_DS_OUTPUT_LEADER} ${datasetName} ${volume}");
            }
        }
        callCheckAccess(checkAccessExePath, dsListFilePath, "output")
    }
    
    static checkDatasetsExist(Set targetDsSet) {
        def allExist = true;
        targetDsSet.each { datasetName->
            def dsn = "'" + datasetName + "'";
            def exists = dsExist(dsn);
            if(!exists){
                allExist = false;
            }
        }
        return (allExist);
    }
    
    static callCheckAccess(checkAccessExePath, dsListFilePath, ioType) {
        def accessResultProcess = [
            "${checkAccessExePath}",
            "-d",
            "${dsListFilePath}"
        ].execute();
        accessResultProcess.waitFor();
        printProcessOutput(accessResultProcess.text);
        def accessResult = accessResultProcess.exitValue();
        if(accessResult != 0){
            printActionTitle("checkaccess:rc=${accessResult}");
            if(137 == accessResult){
                printProcessOutput("checkaccess utility failed. Please verify that checkaccess utility is set as APF authorized by running command \"extattr +a checkaccess\"");
                System.exit(137);
            }
            throw new IOException("These Datasets you listed in PDS mapping can't be used as the ${ioType} of the program!");
        }
    }

    static dsExist(singleQuotedDsName){
        def isExist = false;
        def f = null;
        try {
            f = new ZFile("//" + singleQuotedDsName, "r");
            isExist = true;
        } catch(ZFileException e) {
            if(e.getErrno() == 92) {
                printProcessOutput("Data set $singleQuotedDsName could not be opened for read.")
            }else if (e.getErrno() == 49) {
                printProcessOutput("Data set $singleQuotedDsName could not be located.")
            }else{
                e.printStackTrace();
            }
            // Assume that the file does not exist in this case.
        } finally {
            if (null != f) {
                f.close();
            }
        }

        return(isExist);
    }

    //Clean up after deploy or rollback
    static cleanWorkDir(workdir){
        def versionWorkingDirectory = new File(workdir);
        if (versionWorkingDirectory.exists() && versionWorkingDirectory.isDirectory()) {
            versionWorkingDirectory.deleteDir();
        }
    }

    //Clean up back up data
    static cleanBackUpData(deployBasePath) {
        cleanWorkDir(deployBasePath);
    }

    //Verify copy/ftp result
    static verifyGetArtifectResult(filePath, errorInfo){
        def file = new File(filePath);
        if(!file.exists() || !file.isFile()){
            throw new IOException(errorInfo);
        }
    }

    //Not null or empty input checking
    static inputNotEmptyCheck(input, errorInformation) {
        if (null == input || input.length()<=0) {
            throw new IllegalArgumentException(errorInformation);
        }
    }

    static doDeploymentAction(deployBasePath, tempDsnPrefix, resourceId, componentName, versionName, zosScriptPath, componentVersionWorkingDir, backupPds, hfsTargetDir) {
		
        def versionPathInDeployBase = getVersionPathInDeployBasePath(deployBasePath, resourceId, componentName, versionName, false);
        //Prepare to deploy
        preDeploy(versionPathInDeployBase, versionName);
        //Back Up Pds before deploy current version for rollback
        backUpPdsBeforeDeployment(zosScriptPath, componentVersionWorkingDir, DeploymentConstants.ZOS_TOOLKIT_TRACE_ON, backupPds, hfsTargetDir);
        //Do the deployment
        deploy(zosScriptPath, componentVersionWorkingDir, DeploymentConstants.ZOS_TOOLKIT_TRACE_ON, tempDsnPrefix, hfsTargetDir);
        //Post deployment
        postDeploy(componentVersionWorkingDir, versionPathInDeployBase, backupPds);
    };

    //Prepare to deploy
    static preDeploy(versionDeploybasePath, versionName) {
        printActionTitle("PreDeploy:");
        if(!directoryExist(versionDeploybasePath)) {
            printProcessOutput("Creating directory:" + versionDeploybasePath);
            new File(versionDeploybasePath).mkdirs();
        }
        println "";
    }

    //Call this to do pds back up before deployment, and the backup result will be stored in the working directory
    static backUpPdsBeforeDeployment(ispfScriptPath, componentVersionWorkingDir, traceOn, backupPds, hfsTargetDir) {
        printActionTitle("Backup:");
		
		if(backupPds){
	        def manifestFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.PACKAGE_MANIFEST_FILE_DEPLOY_NAME;
	        def containerMapperFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.CONTAINER_MAPPER_FILE_NAME;
	        def timestamp = new Date().getTime().toString();
			def pkgManifestHelper = new PackageManifestXMLHelper();
			def hasDataSets = pkgManifestHelper.hasDataSets(manifestFilePath);
			def hasHFSFiles = pkgManifestHelper.hasHFSFiles(manifestFilePath);
	
			if(hasDataSets){
		        def backUpPdsProcess = [
		            "${ispfScriptPath}",
		            "${DeploymentConstants.ZOS_TOOLKIT_BACKUP_COMMAND}",
		            "${manifestFilePath}",
		            "${componentVersionWorkingDir}",
		            "${DeploymentConstants.DEPLOY_BACKUP_FILE_NAME}",
		            "${containerMapperFilePath}",
		            "${DeploymentConstants.ZOS_TOOLKIT_BUILDER_VERSION}",
		            "${DeploymentConstants.ZOS_TOOLKIT_RUNTIME_MINIMAL_VERSION}",
		            "${timestamp}",
		            "${traceOn}"
		        ].execute();
		
		        backUpPdsProcess.waitFor();
		
		        def backUpPdsResult = backUpPdsProcess.exitValue();
		        if(backUpPdsResult > 0) {
		            printProcessOutput(backUpPdsProcess.text);
		            printProcessOutput("The backup failed to complete. Look at the CDATA section in previous messages for the failure reason. Check for REASON-CODE entries if they exist.");
		            System.exit(1);
		        } else {
		            printProcessOutput(backUpPdsProcess.text);
		        }
			}
			
			if(hasHFSFiles){
				def ant = new AntBuilder();
				ant.taskdef(name:"backUpHFSFiles", classname:"com.ibm.team.enterprise.deployment.hfs.BackUpHFSFilesTask");
				//ant.property( name: "team.enterprise.deployment.hfs.runtimeRoot.dir", hfsTargetDir );
				
				ant.backUpHFSFiles (
					manifest: manifestFilePath,
					outputDir: componentVersionWorkingDir,
					outputFile : DeploymentConstants.DEPLOY_BACKUP_FILE_NAME,
					rootDir: hfsTargetDir );
	
			}
		}else{
			printProcessOutput("Backup is skipped. ");
		}
		println ""
    }

    //Call this method to do deploy, which will use those artifacts of a version and thos mapping file to move member into target datset
    static deploy(ispfScriptPath, componentVersionWorkingDir, traceOn, tempDsnPrefix, hfsTargetDir) {
        printActionTitle("Deploy:");
		println "";
		
        def manifestFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.PACKAGE_MANIFEST_FILE_DEPLOY_NAME;
        def packageZipFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.PACKAGE_FILE_NAME;
        def containerMapperFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.CONTAINER_MAPPER_FILE_NAME;
        def uninstallFile = "";//Just align with the interface used in zosdeploy.xml
	    def pkgManifestHelper = new PackageManifestXMLHelper();
		def hasDataSets = pkgManifestHelper.hasDataSets(manifestFilePath);
		def hasHFSFiles = pkgManifestHelper.hasHFSFiles(manifestFilePath);

		if(hasDataSets){
			printActionTitle("Deploy data sets:");
	        def deployPdsProcess = [
	            "${ispfScriptPath}",
	            "${DeploymentConstants.ZOS_TOOLKIT_DEPLOY_COMMAND}",
	            "${manifestFilePath}",
	            "${componentVersionWorkingDir}",
	            "${DeploymentConstants.PACKAGE_FILE_NAME}",
	            "${containerMapperFilePath}",
	            "${DeploymentConstants.ZOS_TOOLKIT_BUILDER_VERSION}",
	            "${DeploymentConstants.ZOS_TOOLKIT_RUNTIME_MINIMAL_VERSION}",
	            "${uninstallFile}",
	            "${traceOn}",
	            "${tempDsnPrefix}"
	        ].execute();
	
	        deployPdsProcess.waitFor();
	        def deployPdsResult = deployPdsProcess.exitValue();
	        if(deployPdsResult>0) {
	            printProcessOutput(deployPdsProcess.text);
	            printProcessOutput("The deployment failed to complete. Look at the CDATA section in previous messages for the failure reason. Check for REASON-CODE entries if they exist.");
	            System.exit(1);
	        }else{
	            printProcessOutput(deployPdsProcess.text);
	        }
			println "";
		}

		if(hasHFSFiles){
			printActionTitle("Deploy HFS files:");
			
			def ant = new AntBuilder();
			ant.taskdef(name:"deployHFSFiles", classname:"com.ibm.team.enterprise.deployment.hfs.DeployHFSFilesTask");
			//ant.property( name: "team.enterprise.deployment.hfs.runtimeRoot.dir", hfsTargetDir );
			def unpackDir = componentVersionWorkingDir + File.separator + DeploymentConstants.HFS_UNPACK_DIR;
			
			if(new File(packageZipFilePath).exists()){
				//unpack package.zip if exists
				ant.delete(dir  : unpackDir, quiet : "true");
				ant.mkdir (dir  : unpackDir);
				ant.untar (dest : unpackDir,
						   src  : packageZipFilePath,
						   overwrite : "true" );
			}
			
			ant.deployHFSFiles (
				manifest: manifestFilePath,
				outputDir: unpackDir,
				targetDir: hfsTargetDir
			)

	        ant.delete(dir  : unpackDir, quiet : "true");
			println "";
		}
		
    }

    //Copy those result file into deploy base path, which will be used to do rollback etc
    static postDeploy(componentVersionWorkingDir, versionDeploybasePath, backupPds) {
        printActionTitle("PostDeploy:");

		def deployDeltaFile = new File(componentVersionWorkingDir + File.separator + DeploymentConstants.DEPLOY_DELTA_FILE_NAME);
		if(deployDeltaFile.exists()){
			//Print out the deploy result file contents
			printActionTitle("Deploy Report:");
		    def deployResult = deployDeltaFile.getText(DeploymentConstants.ENCODING);
			printProcessOutput(deployResult);
		}
        println "";

		printActionTitle("Store deploy results:");
        def ant = new AntBuilder();
        copyFile(ant, componentVersionWorkingDir, versionDeploybasePath, DeploymentConstants.PACKAGE_MANIFEST_FILE_NAME, true);
        copyFile(ant, componentVersionWorkingDir, versionDeploybasePath, DeploymentConstants.DEPLOY_DELTA_FILE_NAME, DeploymentConstants.ROLLBACK_MANIFEST_FILE_NAME, true);
        copyFile(ant, componentVersionWorkingDir, versionDeploybasePath, DeploymentConstants.CONTAINER_MAPPER_FILE_NAME, true);
        copyFile(ant, componentVersionWorkingDir, versionDeploybasePath, DeploymentConstants.CHECK_ACCESS_DS_FILE_NAME, true);
        //Copy backup.zip
        copyFile(ant, componentVersionWorkingDir, versionDeploybasePath, DeploymentConstants.DEPLOY_BACKUP_FILE_NAME, true);
        println "";
    }

    static postDeployForGenericOnly(deployBasePath, resourceId, componentName, versionName, componentVersionWorkingDir) {
        printActionTitle("PostDeploy:");
        def versionPathInDeployBase = getVersionPathInDeployBasePath(deployBasePath, resourceId, componentName, versionName, false);

        def ant = new AntBuilder();
        copyFile(ant, componentVersionWorkingDir, versionPathInDeployBase, DeploymentConstants.PACKAGE_MANIFEST_FILE_NAME, true);

        println "";
    }

    //Call this method to do deploy, which will use those artifacts of a version and thos mapping file to move member into target datset
    static rollback(ispfScriptPath, componentVersionWorkingDir, traceOn, tempDsnPrefix, hfsTargetDir) {
        printActionTitle("Rollback:");

        def rollbackManifestFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.ROLLBACK_MANIFEST_FILE_NAME;
        def containerMapperFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.CONTAINER_MAPPER_FILE_NAME;
        def uninstallFile = "";//Just align with the interface used in zosdeploy.xml
		def backupZipFilePath = componentVersionWorkingDir + File.separator + DeploymentConstants.DEPLOY_BACKUP_FILE_NAME;

		printProcessOutput(new File(rollbackManifestFilePath).getText(DeploymentConstants.ENCODING));
		println "";
				
		def pkgManifestHelper = new PackageManifestXMLHelper();
		def hasDataSets = pkgManifestHelper.hasDataSets(rollbackManifestFilePath);
		def hasHFSFiles = pkgManifestHelper.hasHFSFiles(rollbackManifestFilePath);

		if(hasDataSets){	
			printActionTitle("Rollback data sets:");
	        def rollbackPdsProcess = [
	            "${ispfScriptPath}",
	            "${DeploymentConstants.ZOS_TOOLKIT_ROLLBACK_COMMAND}",
	            "${rollbackManifestFilePath}",
	            "${componentVersionWorkingDir}",
	            "${DeploymentConstants.DEPLOY_BACKUP_FILE_NAME}",
	            "${containerMapperFilePath}",
	            "${DeploymentConstants.ZOS_TOOLKIT_BUILDER_VERSION}",
	            "${DeploymentConstants.ZOS_TOOLKIT_RUNTIME_MINIMAL_VERSION}",
	            "${uninstallFile}",
	            "${traceOn}",
	            "${tempDsnPrefix}"
	        ].execute();
	
	        rollbackPdsProcess.waitFor();
	        def deployPdsResult = rollbackPdsProcess.exitValue();
	        if(deployPdsResult>0) {
	            printProcessOutput(rollbackPdsProcess.text);
	            printProcessOutput("The rollback failed to complete. Look at the CDATA section in previous messages for the failure reason. Check for REASON-CODE entries if they exist.");
	            System.exit(1);
	        } else {
	            printProcessOutput(rollbackPdsProcess.text);
	        }
			println "";
		}
		
		if(hasHFSFiles){
			printActionTitle("Rollback HFS files:");
			def ant = new AntBuilder();
			ant.taskdef(name:"deployHFSFiles", classname:"com.ibm.team.enterprise.deployment.hfs.DeployHFSFilesTask");
			//ant.property( name: "team.enterprise.deployment.hfs.runtimeRoot.dir", hfsTargetDir );
			def unpackDir = componentVersionWorkingDir + File.separator + DeploymentConstants.HFS_UNPACK_DIR;
	
			if(new File(backupZipFilePath).exists()){
				//unpack package.zip if exists
				ant.delete(dir  : unpackDir, quiet : "true");
				ant.mkdir (dir  : unpackDir);
				ant.untar (dest : unpackDir,
						   src  : backupZipFilePath,
						   overwrite : "true" );
			}
			
			ant.deployHFSFiles (
				manifest: rollbackManifestFilePath,
				outputDir: unpackDir,
				targetDir: hfsTargetDir
			)

			ant.delete(dir  : unpackDir, quiet : "true");
			println "";
		}
    }
	
	
	
	

    private static printProcessOutput(text) {
        text.eachLine { it->
            println("\t" + it);
        }
    }

    static printActionTitle(text) {
        println "  "+text;
    }

    static copyFile(antbuilder, componentVersionWorkingDir, versionDeploybasePath, fileName,verbose) {
        def src = componentVersionWorkingDir + File.separator + fileName;
        def target = versionDeploybasePath + File.separator + fileName;
        if(fileExists(src)){
            antbuilder.copy(verbose: verbose, file:"${src}", tofile:"${target}",overwrite: "true");
        }
    }

    static copyFile(antbuilder, componentVersionWorkingDir, versionDeploybasePath, fileName, targetFilename, verbose) {
        def src = componentVersionWorkingDir + File.separator + fileName;
        def target = versionDeploybasePath + File.separator + targetFilename;
        if(fileExists(src)){
            antbuilder.copy(verbose: verbose, file:"${src}", tofile:"${target}", overwrite:"true" );
        }
    }

}
