com.dotcms.publisher.pusher.PushPublisher.java Source code

Java tutorial

Introduction

Here is the source code for com.dotcms.publisher.pusher.PushPublisher.java

Source

package com.dotcms.publisher.pusher;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.io.FileUtils;

import com.dotcms.enterprise.LicenseUtil;
import com.dotcms.enterprise.publishing.remote.bundler.CategoryBundler;
import com.dotcms.enterprise.publishing.remote.bundler.ContainerBundler;
import com.dotcms.enterprise.publishing.remote.bundler.ContentBundler;
import com.dotcms.enterprise.publishing.remote.bundler.DependencyBundler;
import com.dotcms.enterprise.publishing.remote.bundler.FolderBundler;
import com.dotcms.enterprise.publishing.remote.bundler.HTMLPageBundler;
import com.dotcms.enterprise.publishing.remote.bundler.HostBundler;
import com.dotcms.enterprise.publishing.remote.bundler.LanguageBundler;
import com.dotcms.enterprise.publishing.remote.bundler.LinkBundler;
import com.dotcms.enterprise.publishing.remote.bundler.RelationshipBundler;
import com.dotcms.enterprise.publishing.remote.bundler.StructureBundler;
import com.dotcms.enterprise.publishing.remote.bundler.TemplateBundler;
import com.dotcms.publisher.business.DotPublisherException;
import com.dotcms.publisher.business.EndpointDetail;
import com.dotcms.publisher.business.PublishAuditAPI;
import com.dotcms.publisher.business.PublishAuditHistory;
import com.dotcms.publisher.business.PublishAuditStatus;
import com.dotcms.publisher.business.PublishQueueElement;
import com.dotcms.publisher.endpoint.bean.PublishingEndPoint;
import com.dotcms.publisher.util.TrustFactory;
import com.dotcms.publishing.BundlerUtil;
import com.dotcms.publishing.DotPublishingException;
import com.dotcms.publishing.PublishStatus;
import com.dotcms.publishing.Publisher;
import com.dotcms.publishing.PublisherConfig;
import com.dotmarketing.cms.factories.PublicEncryptionFactory;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;

public class PushPublisher extends Publisher {
    private PublishAuditAPI pubAuditAPI = PublishAuditAPI.getInstance();
    private TrustFactory tFactory;

    @Override
    public PublisherConfig init(PublisherConfig config) throws DotPublishingException {
        if (LicenseUtil.getLevel() < 300)
            throw new RuntimeException("need an enterprise pro license to run this bundler");

        this.config = super.init(config);
        tFactory = new TrustFactory();

        return this.config;

    }

    @Override
    public PublisherConfig process(final PublishStatus status) throws DotPublishingException {
        if (LicenseUtil.getLevel() < 300)
            throw new RuntimeException("need an enterprise pro license to run this bundler");

        PublishAuditHistory currentStatusHistory = null;
        try {
            //Compressing bundle
            File bundleRoot = BundlerUtil.getBundleRoot(config);

            ArrayList<File> list = new ArrayList<File>(1);
            list.add(bundleRoot);
            File bundle = new File(
                    bundleRoot + File.separator + ".." + File.separator + config.getId() + ".tar.gz");
            PushUtils.compressFiles(list, bundle, bundleRoot.getAbsolutePath());

            //Retriving enpoints and init client
            List<PublishingEndPoint> endpoints = ((PushPublisherConfig) config).getEndpoints();
            Map<String, List<PublishingEndPoint>> endpointsMap = new HashMap<String, List<PublishingEndPoint>>();
            List<PublishingEndPoint> buffer = null;
            //Organize the endpoints grouping them by groupId
            for (PublishingEndPoint pEndPoint : endpoints) {

                String gid = UtilMethods.isSet(pEndPoint.getGroupId()) ? pEndPoint.getGroupId() : pEndPoint.getId();

                if (endpointsMap.get(gid) == null)
                    buffer = new ArrayList<PublishingEndPoint>();
                else
                    buffer = endpointsMap.get(gid);

                buffer.add(pEndPoint);

                // put in map with either the group key or the id if no group is set
                endpointsMap.put(gid, buffer);

            }

            ClientConfig cc = new DefaultClientConfig();

            if (Config.getStringProperty("TRUSTSTORE_PATH") != null
                    && !Config.getStringProperty("TRUSTSTORE_PATH").trim().equals(""))
                cc.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
                        new HTTPSProperties(tFactory.getHostnameVerifier(), tFactory.getSSLContext()));
            Client client = Client.create(cc);

            //Updating audit table
            currentStatusHistory = pubAuditAPI.getPublishAuditStatus(config.getId()).getStatusPojo();

            currentStatusHistory.setPublishStart(new Date());
            pubAuditAPI.updatePublishAuditStatus(config.getId(), PublishAuditStatus.Status.SENDING_TO_ENDPOINTS,
                    currentStatusHistory);
            //Increment numTries
            currentStatusHistory.addNumTries();

            boolean hasError = false;
            int errorCounter = 0;

            for (String group : endpointsMap.keySet()) {
                List<PublishingEndPoint> groupList = endpointsMap.get(group);

                boolean sent = false;
                for (PublishingEndPoint endpoint : groupList) {
                    EndpointDetail detail = new EndpointDetail();
                    try {
                        FormDataMultiPart form = new FormDataMultiPart();
                        form.field("AUTH_TOKEN", retriveKeyString(
                                PublicEncryptionFactory.decryptString(endpoint.getAuthKey().toString())));

                        form.field("GROUP_ID", UtilMethods.isSet(endpoint.getGroupId()) ? endpoint.getGroupId()
                                : endpoint.getId());

                        form.field("ENDPOINT_ID", endpoint.getId());
                        form.bodyPart(new FileDataBodyPart("bundle", bundle, MediaType.MULTIPART_FORM_DATA_TYPE));

                        //Sending bundle to endpoint
                        WebResource resource = client.resource(endpoint.toURL() + "/api/bundlePublisher/publish");

                        ClientResponse response = resource.type(MediaType.MULTIPART_FORM_DATA)
                                .post(ClientResponse.class, form);

                        if (response.getClientResponseStatus().getStatusCode() == HttpStatus.SC_OK) {
                            detail.setStatus(PublishAuditStatus.Status.BUNDLE_SENT_SUCCESSFULLY.getCode());
                            detail.setInfo("Everything ok");
                            sent = true;
                        } else {
                            detail.setStatus(PublishAuditStatus.Status.FAILED_TO_SENT.getCode());
                            detail.setInfo("Returned " + response.getClientResponseStatus().getStatusCode()
                                    + " status code " + "for the endpoint " + endpoint.getId() + "with address "
                                    + endpoint.getAddress());
                        }
                    } catch (Exception e) {
                        hasError = true;
                        detail.setStatus(PublishAuditStatus.Status.FAILED_TO_SENT.getCode());

                        String error = "An error occured for the endpoint " + endpoint.getId() + " with address "
                                + endpoint.getAddress() + ".  Error: " + e.getMessage();

                        detail.setInfo(error);

                        Logger.error(this.getClass(), error);
                    }

                    currentStatusHistory.addOrUpdateEndpoint(group, endpoint.getId(), detail);

                    if (sent)
                        break;
                }

                if (!sent) {
                    hasError = true;
                    errorCounter++;
                }
            }

            if (!hasError) {
                //Updating audit table
                currentStatusHistory.setPublishEnd(new Date());
                pubAuditAPI.updatePublishAuditStatus(config.getId(),
                        PublishAuditStatus.Status.BUNDLE_SENT_SUCCESSFULLY, currentStatusHistory);

                //Deleting queue records
                //pubAPI.deleteElementsFromPublishQueueTable(config.getId());
            } else {
                if (errorCounter == endpointsMap.size()) {
                    pubAuditAPI.updatePublishAuditStatus(config.getId(),
                            PublishAuditStatus.Status.FAILED_TO_SEND_TO_ALL_GROUPS, currentStatusHistory);
                } else {
                    pubAuditAPI.updatePublishAuditStatus(config.getId(),
                            PublishAuditStatus.Status.FAILED_TO_SEND_TO_SOME_GROUPS, currentStatusHistory);
                }
            }

            return config;

        } catch (Exception e) {
            //Updating audit table
            try {
                pubAuditAPI.updatePublishAuditStatus(config.getId(), PublishAuditStatus.Status.FAILED_TO_PUBLISH,
                        currentStatusHistory);
            } catch (DotPublisherException e1) {
                throw new DotPublishingException(e.getMessage());
            }

            Logger.error(this.getClass(), e.getMessage(), e);
            throw new DotPublishingException(e.getMessage());

        }
    }

    private String retriveKeyString(String token) throws IOException {
        String key = null;
        if (token.contains(File.separator)) {
            File tokenFile = new File(token);
            if (tokenFile != null && tokenFile.exists())
                key = FileUtils.readFileToString(tokenFile, "UTF-8").trim();
        } else {
            key = token;
        }

        return PublicEncryptionFactory.encryptString(key);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public List<Class> getBundlers() {
        boolean buildCategories = false;
        for (PublishQueueElement element : ((PushPublisherConfig) config).getAssets())
            if (element.getType().equals("category"))
                buildCategories = true;
        List<Class> list = new ArrayList<Class>();

        //The order is important cause 
        //I need to add all containers associated with templates

        /**
         * ISSUE #2244: https://github.com/dotCMS/dotCMS/issues/2244
         * 
         */
        if (buildCategories)
            list.add(CategoryBundler.class);
        else {
            list.add(DependencyBundler.class);
            list.add(HostBundler.class);
            list.add(ContentBundler.class);
            list.add(FolderBundler.class);
            list.add(TemplateBundler.class);
            list.add(ContainerBundler.class);
            list.add(HTMLPageBundler.class);
            list.add(LinkBundler.class);

            if (Config.getBooleanProperty("PUSH_PUBLISHING_PUSH_STRUCTURES")) {
                list.add(StructureBundler.class);
                /**
                 * ISSUE #2222: https://github.com/dotCMS/dotCMS/issues/2222
                 * 
                 */
                list.add(RelationshipBundler.class);
            }
            list.add(LanguageBundler.class);
        }

        return list;
    }

}