org.wso2.carbon.humantask.core.deployment.ArchiveBasedHumanTaskDeploymentUnitBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.humantask.core.deployment.ArchiveBasedHumanTaskDeploymentUnitBuilder.java

Source

/*
 * Copyright (c) 2011, 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.deployment;

import org.apache.axis2.util.XMLUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.humantask.HumanInteractionsDocument;
import org.wso2.carbon.humantask.core.HumanTaskConstants;
import org.wso2.carbon.humantask.core.deployment.config.HTDeploymentConfigDocument;
import org.wso2.carbon.humantask.core.deployment.config.THTDeploymentConfig;
import org.wso2.carbon.humantask.core.utils.FileUtils;
import org.wso2.carbon.utils.CarbonUtils;
import org.xml.sax.SAXException;

import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Process HumanTask zip archive to get humanTask related files
 * Are we doing this? This class is no longer used since a Registry Handler is used to get the job done
 */
public class ArchiveBasedHumanTaskDeploymentUnitBuilder extends HumanTaskDeploymentUnitBuilder {
    private static Log log = LogFactory.getLog(ArchiveBasedHumanTaskDeploymentUnitBuilder.class);

    private File humantaskDir;

    private String fileName;

    private int tenantId;

    private long version;

    private String md5sum;

    private List<Definition> wsdlDefinitions = new ArrayList<Definition>();

    private InputStream hiDefinition;

    private InputStream hiConfiguration;

    private HTDeploymentConfigDocument hiConf;

    private File humanTaskDefinitionFile;

    private Map<String, InputStream> wsdlsMap = new HashMap<String, InputStream>();

    private Map<String, InputStream> schemasMap = new HashMap<String, InputStream>();

    private static final FileFilter wsdlFilter = new FileFilter() {
        public boolean accept(File path) {
            return path.getName().endsWith(".wsdl") && path.isFile();
        }
    };

    private static final FileFilter xsdFilter = new FileFilter() {
        public boolean accept(File path) {
            return path.getName().endsWith(".xsd") && path.isFile();
        }
    };

    private static final FileFilter humantaskFilter = new FileFilter() {
        public boolean accept(File path) {
            return path.getName().endsWith(HumanTaskConstants.HUMANTASK_FILE_EXT) && path.isFile();
        }
    };

    // Build human task deployment unit with unextracted archive
    public ArchiveBasedHumanTaskDeploymentUnitBuilder(File hiArchiveZip, int tenantId, long version, String md5sum)
            throws HumanTaskDeploymentException {
        String hiArchiveZipName = hiArchiveZip.getName();
        this.fileName = FilenameUtils.removeExtension(hiArchiveZipName);
        this.tenantId = tenantId;
        this.version = version;
        this.md5sum = md5sum;
        humantaskDir = extractHumanTaskArchive(hiArchiveZip, tenantId, version);
        buildHumanInteractionDocuments();
        buildDeploymentConfiguration();
        buildWSDLs();
        buildSchemas();
    }

    // Build human task deployment unit with the
    public ArchiveBasedHumanTaskDeploymentUnitBuilder(File extractedTaskArchive, int tenantId, long version,
            String packageName, String md5sum) throws HumanTaskDeploymentException {
        this.fileName = packageName;
        this.version = version;
        this.humantaskDir = extractedTaskArchive;
        this.tenantId = tenantId;
        this.md5sum = md5sum;
        buildHumanInteractionDocuments();
        buildDeploymentConfiguration();
        buildWSDLs();
        buildSchemas();
    }

    @Override
    public void buildHumanInteractionDocuments() throws HumanTaskDeploymentException {
        if (hiDefinition == null) {
            List<File> hiDefinitionFiles = FileUtils.directoryEntriesInPath(humantaskDir, humantaskFilter);
            if (hiDefinitionFiles.size() != 1) {
                String errMsg;
                if (hiDefinitionFiles.size() == 0) {
                    errMsg = "No human task definition files were found in " + fileName;
                } else {
                    errMsg = hiDefinitionFiles.size() + " human task definition files were found in " + fileName;
                }
                log.error(errMsg);
                throw new HumanTaskDeploymentException(errMsg);
            }

            try {
                hiDefinition = new FileInputStream(hiDefinitionFiles.get(0));
                humanTaskDefinitionFile = hiDefinitionFiles.get(0);
            } catch (FileNotFoundException e) {
                log.error(e.getMessage());
                throw new HumanTaskDeploymentException("Error building humantask archive; " + fileName, e);
            }
        }
    }

    @Override
    public void buildDeploymentConfiguration() throws HumanTaskDeploymentException {
        if (hiConfiguration == null) {
            File humantaskConfFile = new File(humantaskDir, "htconfig.xml");
            if (!humantaskConfFile.exists()) {
                String errMsg = "htconfig.xml file not found for the " + fileName;
                log.error(errMsg);
                throw new HumanTaskDeploymentException(errMsg);
            }
            try {
                hiConfiguration = new FileInputStream(humantaskConfFile);
            } catch (FileNotFoundException e) {
                log.error(e.getMessage());
                throw new HumanTaskDeploymentException("Error building humantask archive: " + fileName, e);
            }
        }
    }

    @Override
    public void buildWSDLs() throws HumanTaskDeploymentException {
        HashSet<Definition> tmpWsdlDefinitions = new HashSet<>();
        URI baseUri = humantaskDir.toURI();
        for (File file : FileUtils.directoryEntriesInPath(humantaskDir, wsdlFilter)) {

            try {
                URI uri = baseUri.relativize(file.toURI());
                if (!uri.isAbsolute()) {
                    File f = new File(baseUri.getPath() + File.separator + uri.getPath());
                    URI abUri = f.toURI();
                    if (abUri.isAbsolute()) {
                        uri = abUri;
                    }
                }

                WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
                reader.setFeature(HumanTaskConstants.JAVAX_WSDL_VERBOSE_MODE_KEY, false);
                reader.setFeature("javax.wsdl.importDocuments", true);
                Definition definition = reader.readWSDL(new HumanTaskWSDLLocator(uri));
                if (definition != null) {
                    tmpWsdlDefinitions.add(definition);
                }

            } catch (WSDLException e) {
                log.error("Error processing wsdl " + file.getName());
                throw new HumanTaskDeploymentException(" Error processing wsdl ", e);
            } catch (URISyntaxException e) {
                log.error("Invalid uri in reading wsdl ", e);
                throw new HumanTaskDeploymentException(" Invalid uri in reading wsdl ", e);
            }
        }
        // Optimizing WSDLs imports. Using HashSet to avoid duplicate entices.
        HashSet<Definition> optimizedDefinitions = new HashSet<>();
        HTDeploymentConfigDocument htDeploymentConfigDocument = getHTDeploymentConfigDocument();

        // Iterating Tasks.
        THTDeploymentConfig.Task[] taskArray = htDeploymentConfigDocument.getHTDeploymentConfig().getTaskArray();
        if (taskArray != null) {
            for (THTDeploymentConfig.Task task : taskArray) {
                QName taskService = task.getPublish().getService().getName();
                Definition taskServiceDefinition = getDefinition(taskService, tmpWsdlDefinitions);
                if (log.isDebugEnabled()) {
                    log.debug("Optimizing WSDL import for Task : " + task.getName());
                }
                if (taskServiceDefinition != null) {
                    optimizedDefinitions.add(taskServiceDefinition);
                    if (log.isDebugEnabled()) {
                        log.debug("Added WSDL for Task : " + task.getName() + ", Service : " + taskService
                                + ", Imported/Total definition : " + optimizedDefinitions.size() + "/"
                                + tmpWsdlDefinitions.size());
                    }
                } else {
                    log.warn("Can't find valid WSDL definition for Task" + task.getName() + ", Service: "
                            + taskService);
                }
                QName callbackService = task.getCallback().getService().getName();
                Definition callbackServiceDefinition = getDefinition(callbackService, tmpWsdlDefinitions);
                if (callbackServiceDefinition != null) {
                    optimizedDefinitions.add(callbackServiceDefinition);
                    if (log.isDebugEnabled()) {
                        log.debug("Added WSDL for Task : " + task.getName() + ", Callback Service : "
                                + callbackService + ", Imported/Total definition : " + optimizedDefinitions.size()
                                + "/" + tmpWsdlDefinitions.size());
                    }
                } else {
                    log.warn("Can't find valid WSDL definition for Task : " + task.getName() + ", Callback Service"
                            + callbackService);
                }
            }
        }
        // Iterating Notifications.
        THTDeploymentConfig.Notification[] notificationsArray = htDeploymentConfigDocument.getHTDeploymentConfig()
                .getNotificationArray();
        if (notificationsArray != null) {
            for (THTDeploymentConfig.Notification notification : notificationsArray) {
                QName notificationService = notification.getPublish().getService().getName();
                Definition notificationServiceDefinition = getDefinition(notificationService, tmpWsdlDefinitions);
                if (notificationServiceDefinition != null) {
                    optimizedDefinitions.add(notificationServiceDefinition);
                    if (log.isDebugEnabled()) {
                        log.debug("Added WSDL for Task : " + notification.getName() + ", Callback Service : "
                                + notificationService + ", Imported/Total definition : "
                                + optimizedDefinitions.size() + "/" + tmpWsdlDefinitions.size());
                    }
                } else {
                    log.warn("Can't find valid WSDL definition for Notification " + notification.getName()
                            + ", Service: " + notificationService);
                }
            }
        }
        // Converting HashSet to ArrayList.
        wsdlDefinitions = new ArrayList<>(optimizedDefinitions);
        if (log.isDebugEnabled()) {
            log.debug("Optimized Imported/Total definition : " + wsdlDefinitions.size() + "/"
                    + tmpWsdlDefinitions.size());
        }
    }

    @Override
    public void buildSchemas() throws HumanTaskDeploymentException {
        for (File file : FileUtils.directoryEntriesInPath(humantaskDir, xsdFilter)) {
            InputStream is;
            try {
                is = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                log.error(e.getMessage());
                throw new HumanTaskDeploymentException("Error building humantask archive: " + fileName, e);
            }
            schemasMap.put(file.getName(), is);
        }
    }

    @Override
    public HumanInteractionsDocument getHumanInteractionsDocument() throws HumanTaskDeploymentException {
        HumanInteractionsDocument hiDoc;
        try {
            hiDoc = HumanInteractionsDocument.Factory.parse(hiDefinition);
        } catch (Exception e) {
            String errMsg = "Error occurred while parsing the human interaction definition";
            log.error(errMsg, e);
            throw new HumanTaskDeploymentException(errMsg, e);
        }
        return hiDoc;
    }

    @Override
    public HTDeploymentConfigDocument getHTDeploymentConfigDocument() throws HumanTaskDeploymentException {

        if (hiConf == null) {
            try {
                hiConf = HTDeploymentConfigDocument.Factory.parse(hiConfiguration);
            } catch (Exception e) {
                String errMsg = "Error occurred while parsing the human interaction configuration "
                        + "file: htconfig.xml";
                log.error(errMsg, e);
                throw new HumanTaskDeploymentException(errMsg, e);
            }
        }

        return hiConf;
    }

    @Override
    public String getArchiveName() {
        return fileName;
    }

    public List<Definition> getWsdlDefinitions() throws HumanTaskDeploymentException {
        //        if (wsdlDefinitions.size() == 0) {
        //
        //
        //
        //            for (Map.Entry<String, InputStream> wsdl : wsdlsMap.entrySet()) {
        //                try {
        //                    wsdlDefinitions.add(readInTheWSDLFile(wsdl.getValue(),
        //                                                          CarbonUtils.getCarbonHome() + File.separator +
        //                                                          "repository" + File.separator +
        //                                                          HumanTaskConstants.HUMANTASK_REPO_DIRECTORY +
        //                                                          File.separator + this.tenantId +
        //                                                          File.separator + this.fileName +
        //                                                          File.separator + wsdl.getKey(), false));
        //                } catch (WSDLException e) {
        //                    String errMsg = "Error occurred while converting the wsdl input stream to " +
        //                                    "wsdl definition";
        //                    throw new HumanTaskDeploymentException(errMsg, e);
        //                }
        //            }
        //        }
        return wsdlDefinitions;
    }

    @Override
    public long getVersion() {
        return this.version;
    }

    @Override
    public String getMd5sum() {
        return this.md5sum;
    }

    /**
     * Read the WSDL file given the input stream for the WSDL source
     *
     * @param in           WSDL input stream
     * @param entryName    ZIP file entry name
     * @param fromRegistry whether the wsdl is read from registry
     * @return WSDL Definition
     * @throws javax.wsdl.WSDLException at parser error
     */
    public static Definition readInTheWSDLFile(InputStream in, String entryName, boolean fromRegistry)
            throws WSDLException {

        WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();

        // switch off the verbose mode for all usecases
        reader.setFeature(HumanTaskConstants.JAVAX_WSDL_VERBOSE_MODE_KEY, false);
        reader.setFeature("javax.wsdl.importDocuments", true);

        Definition def;
        Document doc;
        try {
            doc = XMLUtils.newDocument(in);
        } catch (ParserConfigurationException e) {
            throw new WSDLException(WSDLException.PARSER_ERROR, "Parser Configuration Error", e);
        } catch (SAXException e) {
            throw new WSDLException(WSDLException.PARSER_ERROR, "Parser SAX Error", e);

        } catch (IOException e) {
            throw new WSDLException(WSDLException.INVALID_WSDL, "IO Error", e);
        }

        // Log when and from where the WSDL is loaded.
        if (log.isDebugEnabled()) {
            log.debug("Reading 1.1 WSDL with base uri = " + entryName);
            log.debug("  the document base uri = " + entryName);
        }
        if (fromRegistry) {
            throw new UnsupportedOperationException(
                    "This operation is not currently " + "supported in this version of WSO2 BPS.");
        } else {
            def = reader.readWSDL(entryName, doc.getDocumentElement());
        }
        def.setDocumentBaseURI(entryName);
        return def;

    }

    public File getHumanTaskDefinitionFile() {
        return humanTaskDefinitionFile;
    }

    //    public void persist() throws HumanTaskDeploymentException {
    //        //create a collection for the DU n create relevent associations
    //        Registry configRegistry;
    //        try {
    //            configRegistry = HumanTaskServiceComponent.getRegistryService().getConfigSystemRegistry();
    //        } catch (RegistryException e) {
    //            String errMsg = "Error while getting config registry";
    //            log.error(errMsg, e);
    //            throw new HumanTaskDeploymentException(errMsg, e);
    //        }
    //
    //        String zipName = getFileName();
    //        Collection du;
    //        try {
    //            if (configRegistry.resourceExists(HumanTaskConstants.HT_DEP_UNITS_REPO_LOCATION + zipName)) {
    //                String errMsg = zipName + " is already exist.";
    //                log.error(errMsg);
    //                throw new HumanTaskDeploymentException(errMsg);
    //            }
    //            du = configRegistry.newCollection();
    //        } catch (RegistryException e) {
    //            //TODO Roleback WSDLS n Schemas in Governance Registry
    //            String errMsg = "Error accessing registry";
    //            log.error(errMsg, e);
    //            throw new HumanTaskDeploymentException(errMsg, e);
    //        }
    //
    //        if (du != null) {
    //            String errMsg = "Error puting the collection to registry";
    //            try {
    //                du.addProperty("WSDL_COUNT", Integer.toString(wsdlsMap.size()));
    //                //du.addProperty("STATUS", "DEPLOYED");
    //                configRegistry.put(HumanTaskConstants.HT_DEP_UNITS_REPO_LOCATION + zipName + "/", du);
    //            } catch (RegistryException e) {
    //                //TODO Roleback WSDLS n Schemas in Governance Registry
    //                log.error(errMsg, e);
    //                throw new HumanTaskDeploymentException(errMsg, e);
    //            }
    //
    //            try {
    //                for (Map.Entry<String, InputStream> wsdlEntry : wsdlsMap.entrySet()) {
    //                    Resource wsdlResource = configRegistry.newResource();
    //                    wsdlResource.setContentStream(getWsdlInputStream(wsdlEntry));
    //                    configRegistry.put(HumanTaskConstants.HT_DEP_UNITS_REPO_LOCATION +
    //                                       this.fileName + "/" + wsdlEntry.getKey(), wsdlResource);
    //                }
    //
    //                for (Map.Entry<String, InputStream> schemaEntry : schemasMap.entrySet()) {
    //                    Resource schemaResource = configRegistry.newResource();
    //                    schemaResource.setContentStream(getSchemaInputStream(schemaEntry));
    //                    configRegistry.put(HumanTaskConstants.HT_DEP_UNITS_REPO_LOCATION +
    //                                       this.fileName + "/" + schemaEntry.getKey(), schemaResource);
    //                }
    //            } catch (RegistryException e) {
    //                log.error(errMsg, e);
    //                throw new HumanTaskDeploymentException(errMsg, e);
    //            } catch (IOException e) {
    //                log.error(errMsg, e);
    //                throw new HumanTaskDeploymentException(errMsg, e);
    //            }
    //
    //            Resource fileResource;
    //            try {
    //                fileResource = configRegistry.newResource();
    //            } catch (RegistryException e) {
    //                String erMsg = "Error creating new resource";
    //                log.error(erMsg, e);
    //                throw new HumanTaskDeploymentException(erMsg, e);
    //            }
    //
    //            if (fileResource != null) {
    //                try {
    //                    fileResource.setContent(hiDefinition);
    //                    configRegistry.put(HumanTaskConstants.HT_DEP_UNITS_REPO_LOCATION + zipName +
    //                                       "/" + "htDefinition.ht", fileResource);
    //                    fileResource.setContentStream(hiConfiguration);
    //                    configRegistry.put(HumanTaskConstants.HT_DEP_UNITS_REPO_LOCATION + zipName +
    //                                       "/" + "htconfig.xml", fileResource);
    //                } catch (RegistryException e) {
    //                    String erMsg = "Error puting resource to registry";
    //                    log.error(erMsg, e);
    //                    throw new HumanTaskDeploymentException(erMsg, e);
    //                }
    //            }
    //        }
    //    }

    //    public InputStream getWsdlInputStream(Map.Entry<String, InputStream> wsdlEntry)
    //            throws IOException {
    //        InputStream wsdl = wsdlEntry.getValue();
    //        if (wsdl.markSupported()) {
    //            wsdl.reset();
    //        }
    //        return wsdl;
    //    }
    //
    //    public InputStream getSchemaInputStream(Map.Entry<String, InputStream> schemaEntry)
    //            throws IOException {
    //        InputStream schema = schemaEntry.getValue();
    //        schema.reset();
    //        return schema;
    //    }

    /**
     * Extract HumanTask archive to tenant's HumanTask file system repository.
     * Version is passed to the method and the final extract directory will be {taskPackageName}-{version}.
     * Task  version is unique for all task packages.
     * Example. If the task package name is ClaimsApproval and this is the first task to be deployed in the server
     * resulting in task version being 1, then the extracted directory will be
     * ClaimsApproval-1 located in the corresponding tenants humantasks directory
     * @param archiveFile zip file
     * @param tenantId    Tenant ID
     * @return Extracted directory
     * @throws HumanTaskDeploymentException If an error occured
     */
    public static File extractHumanTaskArchive(final File archiveFile, int tenantId, long version)
            throws HumanTaskDeploymentException {
        ZipInputStream zipStream = null;

        try {
            String humanTaskExtractionLocation = CarbonUtils.getCarbonHome() + File.separator + "repository"
                    + File.separator + HumanTaskConstants.HUMANTASK_REPO_DIRECTORY + File.separator + tenantId
                    + File.separator + FilenameUtils.removeExtension(archiveFile.getName()) + "-" + version;

            zipStream = new ZipInputStream(new FileInputStream(archiveFile));
            ZipEntry entry;

            while ((entry = zipStream.getNextEntry()) != null) {
                if (entry.isDirectory()) {
                    if (log.isDebugEnabled()) {
                        log.debug("Extracting directory " + entry.getName());
                    }
                    if (!new File(humanTaskExtractionLocation, entry.getName()).mkdirs()
                            && !new File(humanTaskExtractionLocation, entry.getName()).exists()) {
                        throw new HumanTaskDeploymentException("Archive extraction failed. "
                                + "Cannot create directory: "
                                + new File(humanTaskExtractionLocation, entry.getName()).getAbsolutePath() + ".");
                    }
                    continue;
                }

                if (log.isDebugEnabled()) {
                    log.debug("Extracting file " + entry.getName());
                }

                File destFile = new File(humanTaskExtractionLocation, entry.getName());

                if (!destFile.getParentFile().exists() && !destFile.getParentFile().mkdirs()) {
                    throw new HumanTaskDeploymentException("Archive extraction failed. "
                            + "Cannot create directory: " + destFile.getParentFile().getAbsolutePath());
                }
                BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destFile));
                copyInputStream(zipStream, outputStream);
            }

            return new File(humanTaskExtractionLocation);
        } catch (IOException e) {
            String errMsg = "Error occurred during extracting the archive: " + archiveFile;
            log.error(errMsg, e);
            throw new HumanTaskDeploymentException(errMsg, e);
        } finally {
            if (zipStream != null) {
                try {
                    zipStream.close();

                } catch (IOException e) {
                    String errMsg = "Error occurred during extracting the archive: " + archiveFile;
                    log.error(errMsg + e);
                    throw new HumanTaskDeploymentException(errMsg, e);
                }
            }
        }
    }

    private static void copyInputStream(final InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int len;
        while ((len = in.read(buffer)) >= 0) {
            out.write(buffer, 0, len);
        }
        out.close();
    }

    /**
     * Get matching WSDL definition from given WSDL definition list.
     *
     * @param serviceName
     * @param definitions
     * @return
     */
    private Definition getDefinition(QName serviceName, Set<Definition> definitions) {
        for (Definition definition : definitions) {
            if (definition.getTargetNamespace().equals(serviceName.getNamespaceURI())) {
                if (definition.getService(serviceName) != null)
                    return definition;
            }
        }
        return null;
    }
}