org.wso2.carbon.bpel.ui.fileupload.BPELUploadExecutor.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.bpel.ui.fileupload.BPELUploadExecutor.java

Source

/*
 * Copyright (c) 2010, 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.bpel.ui.fileupload;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.dd.DeployDocument;
import org.apache.ode.bpel.dd.TDeployment;
import org.apache.ode.bpel.dd.TInvoke;
import org.apache.ode.bpel.dd.TProvide;
import org.apache.ode.store.DeploymentUnitDir;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.CarbonException;
import org.wso2.carbon.ui.CarbonUIMessage;
import org.wso2.carbon.ui.transports.fileupload.AbstractFileUploadExecutor;
import org.wso2.carbon.utils.FileItemData;
import org.wso2.carbon.utils.ServerConstants;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;

/**
 *
 */
public class BPELUploadExecutor extends AbstractFileUploadExecutor {
    private static final String[] ALLOWED_FILE_EXTENSIONS = new String[] { ".zip" };
    private static Log log = LogFactory.getLog(BPELUploadExecutor.class);

    private static void addDir(File dirObj, ZipOutputStream out, int basePathLen) throws Exception {
        if (dirObj != null && out != null) {
            File[] files = dirObj.listFiles();
            byte[] tmpBuf = new byte[2048];
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        addDir(file, out, basePathLen);
                        continue;
                    }
                    FileInputStream in = null;
                    try {
                        in = new FileInputStream(file.getAbsolutePath());
                        if (log.isDebugEnabled()) {
                            log.debug("Adding: " + file.getAbsolutePath());
                        }
                        out.putNextEntry(new ZipEntry(file.getAbsolutePath().substring(basePathLen)));
                        int len;
                        while ((len = in.read(tmpBuf)) > 0) {
                            out.write(tmpBuf, 0, len);
                        }
                    } finally {
                        if (in != null) {
                            in.close();
                        }
                    }
                }
            }
        }
    }

    public boolean execute(HttpServletRequest request, HttpServletResponse response)
            throws CarbonException, IOException {
        String errMsg;

        response.setContentType("text/html; charset=utf-8");

        PrintWriter out = response.getWriter();
        String webContext = (String) request.getAttribute(CarbonConstants.WEB_CONTEXT);
        String serverURL = (String) request.getAttribute(CarbonConstants.SERVER_URL);
        String cookie = (String) request.getAttribute(ServerConstants.ADMIN_SERVICE_COOKIE);
        Map<String, ArrayList<FileItemData>> fileItemsMap = getFileItemsMap();

        if (fileItemsMap == null || fileItemsMap.isEmpty()) {
            String msg = "File uploading failed.";
            log.error(msg);
            out.write("<textarea>" + "(function(){i18n.fileUplodedFailed();})();" + "</textarea>");
            return true;
        }
        BPELUploaderClient uploaderClient = new BPELUploaderClient(configurationContext, serverURL + "BPELUploader",
                cookie);

        SaveExtractReturn uploadedFiles = null;
        ArrayList<String> extractedFiles = new ArrayList<String>();
        try {
            for (FileItemData fieldData : fileItemsMap.get("bpelFileName")) {
                String fileName = getFileName(fieldData.getFileItem().getName());
                //Check filename for \ charactors. This cannot be handled at the lower stages.
                if (fileName.matches("(.*[\\\\].*[/].*|.*[/].*[\\\\].*)")) {
                    log.error(
                            "BPEL Package Validation Failure: one or many of the following illegal characters are "
                                    + "in " + "the package.\n ~!@#$;%^*()+={}[]| \\<>");
                    throw new Exception("BPEL Package Validation Failure: one or many of the following illegal "
                            + "characters " + "are in the package. ~!@#$;%^*()+={}[]| \\<>");
                }
                //Check file extension.
                checkServiceFileExtensionValidity(fileName, ALLOWED_FILE_EXTENSIONS);

                if (fileName.lastIndexOf('\\') != -1) {
                    int indexOfColon = fileName.lastIndexOf('\\') + 1;
                    fileName = fileName.substring(indexOfColon, fileName.length());
                }
                if (fieldData.getFileItem().getFieldName().equals("bpelFileName")) {
                    uploadedFiles = saveAndExtractUploadedFile(fieldData.getFileItem());
                    extractedFiles.add(uploadedFiles.extractedFile);
                    validateBPELPackage(uploadedFiles.extractedFile);
                    DataSource dataSource = new FileDataSource(uploadedFiles.zipFile);
                    uploaderClient.addUploadedFileItem(new DataHandler(dataSource), fileName, "zip");

                }
            }
            uploaderClient.uploadFileItems();
            String msg = "Your BPEL package been uploaded successfully. Please refresh this page in a"
                    + " while to see the status of the new process.";
            CarbonUIMessage.sendCarbonUIMessage(msg, CarbonUIMessage.INFO, request, response,
                    getContextRoot(request) + "/" + webContext + "/bpel/process_list.jsp");

            return true;
        } catch (Exception e) {
            errMsg = "File upload failed :" + e.getMessage();
            log.error(errMsg, e);
            CarbonUIMessage.sendCarbonUIMessage(errMsg, CarbonUIMessage.ERROR, request, response,
                    getContextRoot(request) + "/" + webContext + "/bpel/upload_bpel.jsp");
        } finally {
            for (String s : extractedFiles) {
                File extractedFile = new File(s);
                if (log.isDebugEnabled()) {
                    log.debug("Cleaning temporarily extracted BPEL artifacts in " + extractedFile.getParent());
                }
                try {
                    FileUtils.cleanDirectory(new File(extractedFile.getParent()));
                } catch (IOException ex) {
                    log.warn("Failed to clean temporary extractedFile.", ex);
                }
            }
        }

        return false;
    }

    public SaveExtractReturn saveAndExtractUploadedFile(FileItem fileItem) throws Exception {
        String serviceUploadDir = getTempUploadDir();
        File servicesDir = new File(serviceUploadDir);
        if (!servicesDir.exists() && !servicesDir.mkdirs()) {
            throw new IOException("Fail to create the directory: " + servicesDir.getAbsolutePath());
        }

        // Writing BPEL archive to file system
        String fileItemName = getFileName(fileItem.getName());
        File uploadedFile = new File(servicesDir, fileItemName);

        if (log.isDebugEnabled()) {
            log.debug("[BPELUI]BPEL Archive Path: " + uploadedFile.getAbsolutePath());
        }

        try {
            fileItem.write(uploadedFile);
        } catch (Exception e) {
            log.error("Error occurred while writing file item to file system.", e);
            throw new Exception("Erorr occurred while writing file item to file system.", e);
        }

        String destinationDir = serviceUploadDir + File.separator
                + fileItemName.substring(0, fileItemName.lastIndexOf('.'));
        if (log.isDebugEnabled()) {
            log.debug("[BPELUI]Bpel package location: " + destinationDir);
        }
        try {
            ArchiveExtractor.extract(uploadedFile, destinationDir);
        } catch (Exception e) {
            log.error("Error extracting archive.", e);
            throw new Exception(e);
        }

        // Handling backward compatibility issues. If user upload BPEL archive which follows the BPS 1.0.1 archive
        // format
        // we need to convert it to new format and upload.
        File deployXml = new File(destinationDir, "deploy.xml");
        if (!deployXml.exists()) {
            String depXmlSrc = fileItemName.substring(0, fileItemName.lastIndexOf('.')) + File.separator
                    + "deploy.xml";
            deployXml = new File(destinationDir, depXmlSrc);
            if (deployXml.exists()
                    && onlyOneChildDir(destinationDir, fileItemName.substring(0, fileItemName.lastIndexOf('.')))) {
                String tempUploadDir = getTempUploadDir();
                File tempDir = new File(tempUploadDir);
                if (!tempDir.exists() && !tempDir.mkdirs()) {
                    throw new IOException("Fail to create the directory: " + tempDir.getAbsolutePath());
                }

                String filesToZipParent = destinationDir + File.separator
                        + fileItemName.substring(0, fileItemName.lastIndexOf('.'));
                String zipLocation = tempDir.getAbsolutePath() + File.separator + fileItemName;
                try {
                    zip(zipLocation, filesToZipParent);
                } catch (Exception e) {
                    throw new Exception(e);
                }

                return new SaveExtractReturn(zipLocation, filesToZipParent);

            }

            throw new Exception("BPEL Archive format error.Please confirm that the file being uploaded is a "
                    + "valid BPEL archive.");
        }

        return new SaveExtractReturn(uploadedFile.getAbsolutePath(), destinationDir);
    }

    private void zip(String zipFile, String sourceDir) throws Exception {
        File dirObj = new File(sourceDir);
        int len = dirObj.getAbsolutePath().length() + 1;
        ZipOutputStream out = null;
        try {
            out = new ZipOutputStream(new FileOutputStream(zipFile));
            if (log.isDebugEnabled()) {
                log.debug("Creating: " + zipFile);
            }
            addDir(dirObj, out, len);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    private String getTempUploadDir() {
        String uuid = generateUUID();
        String tmpDir = "bpelTemp";
        return getWorkingDir() + File.separator + tmpDir + File.separator + uuid + File.separator;
    }

    private boolean onlyOneChildDir(String location, String dirNameToCheck) {
        if (location != null && dirNameToCheck != null) {
            File parentDir = new File(location);
            if (parentDir.isDirectory()) {
                String[] entries = parentDir.list();
                if (entries != null && entries.length == 1 && entries[0].equals(dirNameToCheck)) {
                    return true;
                }
            }
        }

        return false;
    }

    public void validateBPELPackage(String directoryPath) throws Exception {
        DeploymentUnitDir du;
        try {
            du = new DeploymentUnitDir(new File(directoryPath));
        } catch (IllegalArgumentException iae) {
            log.error("BPEL Package Validation Failure.", iae);
            throw new Exception("BPEL Package Validation Failure.", iae);
        }

        //check package for illegal charactors which registry does not support. (~!@#$;%^*()+={}[]|\<>)
        List<File> packageFiles = du.allFiles();
        for (File packageFile : packageFiles) {
            if (!packageFile.getName()
                    .matches("[^\\~\\!\\@\\#\\$\\;\\%\\^\\*\\(\\)\\+ " + "/\\=\\{\\}\\[\\]\\\\|\\<\\>\"\\'\\`]+")) {
                log.error("BPEL Package Validation Failure: one or many of the following illegal characters are in "
                        + "the package.\n ~!@#$;%^*()+={}[]| \\<>\"'`");
                throw new Exception(
                        "BPEL Package Validation Failure: one or many of the following illegal characters" + " "
                                + "are in the package. ~!@#$;%^*()+={}[]| \\<>\"'`");
            }
        }

        try {
            du.compile();
        } catch (RuntimeException ce) {
            log.error("BPEL Process Compilation Failure.", ce);
            throw new Exception("BPEL Compilation Failure!", ce);
        } catch (Exception e) {
            log.error("BPEL Process Compilation Failure.", e);
            throw new Exception("BPEL Compilation Failure!", e);
        }

        du.scan();
        DeployDocument dd = du.getDeploymentDescriptor();
        for (TDeployment.Process processDD : dd.getDeploy().getProcessList()) {
            QName processType = processDD.getType() != null ? processDD.getType() : processDD.getName();

            DeploymentUnitDir.CBPInfo cbpInfo = du.getCBPInfo(processType);
            if (cbpInfo == null) {
                //removeDeploymentArtifacts(deploymentContext, du);
                String logMessage = "Aborting deployment. Cannot find Process definition for type " + processType
                        + ".";
                log.error(logMessage);
                throw new Exception(logMessage);
            }

            for (TProvide tProvide : processDD.getProvideList()) {
                if (tProvide.getService() == null) {
                    String errMsg = "Service element missing for the provide element in deploy.xml";
                    log.error(errMsg);
                    throw new Exception(errMsg);
                }
            }
            for (TInvoke tInvoke : processDD.getInvokeList()) {
                if (tInvoke.getService() == null) {
                    String errMsg = "Service element missing for the invoke element in deploy.xml";
                    log.error(errMsg);
                    throw new Exception(errMsg);
                }
            }
        }
    }

    static class SaveExtractReturn {
        private String zipFile;
        private String extractedFile;

        public SaveExtractReturn(String zipFile, String extractedFile) {
            this.zipFile = zipFile;
            this.extractedFile = extractedFile;
        }
    }
}