org.craftercms.studio.impl.v1.deployment.SyncTargetDeployer.java Source code

Java tutorial

Introduction

Here is the source code for org.craftercms.studio.impl.v1.deployment.SyncTargetDeployer.java

Source

/*
 * Crafter Studio Web-content authoring solution
 * Copyright (C) 2007-2016 Crafter Software Corporation.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.craftercms.studio.impl.v1.deployment;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.craftercms.studio.api.v1.deployment.Deployer;
import org.craftercms.studio.api.v1.log.Logger;
import org.craftercms.studio.api.v1.log.LoggerFactory;
import org.craftercms.studio.api.v1.service.deployment.ContentNotFoundForPublishingException;
import org.craftercms.studio.api.v1.service.deployment.DeploymentException;
import org.craftercms.studio.api.v1.service.deployment.UploadFailedException;
import org.craftercms.studio.api.v1.to.DeploymentEndpointConfigTO;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class SyncTargetDeployer implements Deployer {

    private final static Logger logger = LoggerFactory.getLogger(SyncTargetDeployer.class);

    private static final String TARGET_REQUEST_PARAMETER = "target";
    private static final String VERSION_REQUEST_PARAMETER = "version";
    private static final String PASSWORD_REQUEST_PARAMETER = "password";
    private final static String SITE_REQUEST_PARAMETER = "siteId";
    private final static String DELETED_FILES_REQUEST_PARAMETER = "deletedFiles";
    private final static String CONTENT_LOCATION_REQUEST_PARAMETER = "contentLocation";
    private final static String CONTENT_FILE_REQUEST_PARAMETER = "contentFile";
    private final static String METADATA_FILE_REQUEST_PARAMETER = "metadataFile";

    private final static String FILES_SEPARATOR = ",";
    private final static String LIVE_ENVIRONMENT = "live";
    private final static String PRODUCTION_ENVIRONMENT = "Production";
    private final static String WORK_AREA_ENVIRONMENT = "work-area";

    @Override
    public void deployFile(String site, String path) {

    }

    @Override
    public void deployFiles(String site, List<String> paths) {

    }

    @Override
    public void deleteFile(String site, String path) {

    }

    @Override
    public void deleteFiles(String site, List<String> paths) {

    }

    @Override
    public void deployFiles(String site, List<String> paths, List<String> deletedFiles)
            throws ContentNotFoundForPublishingException, UploadFailedException {
        logger.debug("Start deploying items for site \"{0}\", target \"{1}\", number of items \"{2}\"", site,
                endpointConfig.getName(), paths.size());
        URL requestUrl = null;
        try {
            requestUrl = new URL(endpointConfig.getServerUrl());
        } catch (MalformedURLException e) {
            logger.error("Invalid server URL for target {0}", endpointConfig.getName());
            throw new UploadFailedException(site, endpointConfig.getName(), endpointConfig.getServerUrl(), e);
        }

        ByteArrayPartSource baps = null;
        PartSource metadataPart = null;
        StringPart stringPart = null;
        FilePart filePart = null;

        // TODO: implement reactor version of deployment events
        int cntFiles = 0;
        StringBuilder sbDeletedFiles = new StringBuilder();
        List<Part> formParts = new ArrayList<Part>();

        formParts.add(new StringPart(PASSWORD_REQUEST_PARAMETER, endpointConfig.getPassword()));
        formParts.add(new StringPart(TARGET_REQUEST_PARAMETER, endpointConfig.getTarget()));
        String siteId = endpointConfig.getSiteId();
        if (StringUtils.isEmpty(siteId)) {
            siteId = site;
        }
        formParts.add(new StringPart(SITE_REQUEST_PARAMETER, siteId));

        logger.debug("Preparing deployment items for target {0}", endpointConfig.getName());
        for (String path : paths) {
            logger.debug("Parsing \"{0}\" , site \"{1}\"; for publishing on target \"{2}\"", path, site,
                    endpointConfig.getName());
            logger.debug("Get content for \"{0}\" , site \"{1}\", environment \"{2}\"", path, site, environment);
            File file = new File(getDestinationPath(site, path, environment));
            InputStream input = null;
            try {
                input = FileUtils.openInputStream(file);
                if (input == null || input.available() < 0) {
                    if (file.exists() && !file.isDirectory()) {
                        baps = null;
                        stringPart = null;
                        filePart = null;
                        formParts = null;
                        throw new ContentNotFoundForPublishingException(site, endpointConfig.getName(), path);
                    } else {
                        // Content does not exist - skip deploying file
                        continue;
                    }
                }
            } catch (IOException err) {
                logger.error("Error reading input stream from envirnoment store for content at path: " + path
                        + " site: " + site + " environment: " + environment);
                if (!file.exists()) {
                    logger.error("File expected, but does not exist at path: " + file.getAbsolutePath());
                }
                continue;
            }
            String fileName = file.getName();

            byte[] byteArray = null;

            try {
                byteArray = IOUtils.toByteArray(input);
            } catch (IOException e) {
                logger.error("Error while converting input stream to byte array", e);
                baps = null;
                stringPart = null;
                filePart = null;
                formParts = null;
            } finally {
                IOUtils.closeQuietly(input);
                input = null;
            }
            baps = new ByteArrayPartSource(fileName, byteArray);

            logger.debug("Create http request parameters for \"{0}\" , site \"{1}\"; publishing on target \"{2}\"",
                    path, site, endpointConfig.getName());
            int idx = path.lastIndexOf("/");
            String relativePath = path.substring(0, idx + 1) + fileName;
            stringPart = new StringPart(CONTENT_LOCATION_REQUEST_PARAMETER + cntFiles, relativePath);
            formParts.add(stringPart);
            filePart = new FilePart(CONTENT_FILE_REQUEST_PARAMETER + cntFiles, baps);
            formParts.add(filePart);
            /*
            if (item.getAction() == PublishingSyncItem.Action.MOVE) {
            if (item.getOldPath() != null && !item.getOldPath().equalsIgnoreCase(item.getPath())) {
                LOGGER.debug("Add old path to be deleted for MOVE action (\"{0}\")", item.getOldPath());
                eventItem.setOldPath(item.getOldPath());
                if (sbDeletedFiles.length() > 0) {
                    sbDeletedFiles.append(",").append(item.getOldPath());
                } else {
                    sbDeletedFiles.append(item.getOldPath());
                }
                if (item.getOldPath().endsWith("/" + _indexFile)) {
                    sbDeletedFiles.append(FILES_SEPARATOR).append(item.getOldPath().replace("/" + _indexFile, ""));
                }
            }
            }*/
            cntFiles++;

            // TODO: implement metadata transfer
        }

        for (int i = 0; i < deletedFiles.size(); i++) {
            if (i > 0) {
                sbDeletedFiles.append(FILES_SEPARATOR);
            }
            sbDeletedFiles.append(deletedFiles.get(i));
        }

        if (sbDeletedFiles.length() > 0) {
            formParts.add(new StringPart(DELETED_FILES_REQUEST_PARAMETER, sbDeletedFiles.toString()));
        }
        logger.debug("Create http request to deploy content for target {0} ({1})", endpointConfig.getName(),
                endpointConfig.getTarget());
        PostMethod postMethod = null;
        HttpClient client = null;
        try {
            logger.debug("Create HTTP Post Method");
            postMethod = new PostMethod(requestUrl.toString());
            postMethod.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, true);
            Part[] parts = new Part[formParts.size()];
            for (int i = 0; i < formParts.size(); i++)
                parts[i] = formParts.get(i);
            postMethod.setRequestEntity(new MultipartRequestEntity(parts, postMethod.getParams()));
            client = new HttpClient();

            logger.debug("Execute HTTP POST request \"{0}\"", postMethod.getURI());
            int status = client.executeMethod(postMethod);
            if (status == HttpStatus.SC_OK) {
                logger.info("Successfully deployed on target {0}", endpointConfig.getName());
            } else {
                logger.error("Deployment failed for on target {1}. Deployment agent returned status {2}",
                        endpointConfig.getName(), HttpStatus.getStatusText(status));
                throw new UploadFailedException(site, endpointConfig.getName(), endpointConfig.getServerUrl());
            }
        } catch (HttpException e) {
            logger.error("Publish failed for target {0} due to http protocol exception", endpointConfig.getName());
            throw new UploadFailedException(site, endpointConfig.getName(), endpointConfig.getServerUrl(), e);
        } catch (IOException e) {
            logger.error("Publish failed for target {0} due to I/O (transport) exception",
                    endpointConfig.getName());
            throw new UploadFailedException(site, endpointConfig.getName(), endpointConfig.getServerUrl(), e);
        } finally {
            logger.debug("Release http connection and release resources");
            if (client != null) {
                HttpConnectionManager mgr = client.getHttpConnectionManager();
                if (mgr instanceof SimpleHttpConnectionManager) {
                    ((SimpleHttpConnectionManager) mgr).shutdown();
                }
            }
            if (postMethod != null) {
                postMethod.releaseConnection();
                postMethod = null;
                client = null;
            }
            baps = null;
            stringPart = null;
            filePart = null;
            formParts = null;
        }

        //LOGGER.debug("Publishing deployment event for target \"{0}\" with \"{1}\" items.", target.getName(), 0/*eventItems.size()*/);
        //contentRepository.publishDeployEvent(target.getName(), eventItems);

        logger.info("Deployment successful on target {0}", endpointConfig.getName());
        logger.debug("Finished deploying items for site \"{0}\", target \"{1}\", number of items \"{2}\"", site,
                endpointConfig.getName(), paths.size());
    }

    private String getDestinationPath(String site, String path, String environment) {
        return String.format("%s/%s/%s/%s", environmentsStoreRootPath, site, environment, path);
    }

    public String getEnvironmentsStoreRootPath() {
        return environmentsStoreRootPath;
    }

    public void setEnvironmentsStoreRootPath(String environmentsStoreRootPath) {
        this.environmentsStoreRootPath = environmentsStoreRootPath;
    }

    public String getEnvironment() {
        return environment;
    }

    public void setEnvironment(String environment) {
        this.environment = environment;
    }

    public DeploymentEndpointConfigTO getEndpointConfig() {
        return endpointConfig;
    }

    public void setEndpointConfig(DeploymentEndpointConfigTO endpointConfig) {
        this.endpointConfig = endpointConfig;
    }

    protected String environmentsStoreRootPath;
    protected String environment;
    protected DeploymentEndpointConfigTO endpointConfig;
}