org.jahia.ajax.gwt.helper.SchedulerHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.ajax.gwt.helper.SchedulerHelper.java

Source

/**
 * ==========================================================================================
 * =                   JAHIA'S DUAL LICENSING - IMPORTANT INFORMATION                       =
 * ==========================================================================================
 *
 *                                 http://www.jahia.com
 *
 *     Copyright (C) 2002-2017 Jahia Solutions Group SA. All rights reserved.
 *
 *     THIS FILE IS AVAILABLE UNDER TWO DIFFERENT LICENSES:
 *     1/GPL OR 2/JSEL
 *
 *     1/ GPL
 *     ==================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE GPL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     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/>.
 *
 *
 *     2/ JSEL - Commercial and Supported Versions of the program
 *     ===================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE JSEL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     Alternatively, commercial and supported versions of the program - also known as
 *     Enterprise Distributions - must be used in accordance with the terms and conditions
 *     contained in a separate written agreement between you and Jahia Solutions Group SA.
 *
 *     If you are unsure which license is appropriate for your use,
 *     please contact the sales department at sales@jahia.com.
 */
package org.jahia.ajax.gwt.helper;

import org.apache.commons.lang.StringUtils;
import org.atmosphere.cpr.Broadcaster;
import org.atmosphere.cpr.BroadcasterFactory;
import org.jahia.ajax.gwt.client.data.definition.GWTJahiaNodeProperty;
import org.jahia.ajax.gwt.client.data.job.GWTJahiaJobDetail;
import org.jahia.ajax.gwt.client.service.GWTJahiaServiceException;
import org.jahia.ajax.gwt.client.widget.poller.ProcessPollingEvent;
import org.jahia.ajax.gwt.commons.server.ChannelHolder;
import org.jahia.ajax.gwt.commons.server.JGroupsChannel;
import org.jahia.ajax.gwt.commons.server.ManagedGWTResource;
import org.jahia.services.SpringContextSingleton;
import org.jahia.services.atmosphere.AtmosphereServlet;
import org.jahia.services.content.JCRCallback;
import org.jahia.services.content.JCRSessionWrapper;
import org.jahia.services.content.JCRTemplate;
import org.jahia.services.content.PublicationJob;
import org.jahia.services.content.rules.ActionJob;
import org.jahia.services.content.rules.RuleJob;
import org.jahia.services.content.textextraction.TextExtractorJob;
import org.jahia.services.importexport.ImportJob;
import org.jahia.services.scheduler.BackgroundJob;
import org.jahia.services.scheduler.SchedulerService;
import org.jahia.services.usermanager.JahiaUser;
import org.quartz.*;
import org.quartz.listeners.JobListenerSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
import java.util.*;

/**
 * User: toto
 * Date: Sep 17, 2010
 * Time: 2:04:17 PM
 */
public class SchedulerHelper {
    private Logger logger = LoggerFactory.getLogger(SchedulerHelper.class);

    private static final Comparator<GWTJahiaJobDetail> JOB_COMPARATOR = new Comparator<GWTJahiaJobDetail>() {
        public int compare(GWTJahiaJobDetail o1, GWTJahiaJobDetail o2) {
            return o2.compareTo(o1);
        }
    };

    private SchedulerService scheduler;

    public void setScheduler(SchedulerService scheduler) {
        this.scheduler = scheduler;
    }

    public void start() {
        try {
            scheduler.getScheduler().addGlobalJobListener(new PollingSchedulerListener());
        } catch (SchedulerException e) {
            logger.error("Cannot register job listener", e);
        }
    }

    private Long getLong(JobDataMap jobDataMap, String key) {
        if (jobDataMap.get(key) == null) {
            return null;
        }
        return Long.parseLong(jobDataMap.getString(key));
    }

    private List<GWTJahiaJobDetail> convertToGWTJobs(List<JobDetail> jobDetails) {
        List<GWTJahiaJobDetail> jobs = new ArrayList<GWTJahiaJobDetail>();
        for (JobDetail jobDetail : jobDetails) {
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
            Date created = (Date) jobDataMap.get(BackgroundJob.JOB_CREATED);
            final String status = jobDataMap.getString(BackgroundJob.JOB_STATUS);
            final String user = StringUtils.substringAfterLast(jobDataMap.getString(BackgroundJob.JOB_USERKEY),
                    "/");
            final String message = jobDataMap.getString(BackgroundJob.JOB_MESSAGE);
            final Long beginTime = getLong(jobDataMap, BackgroundJob.JOB_BEGIN);
            final Long endTime = getLong(jobDataMap, BackgroundJob.JOB_END);
            final String site = jobDataMap.getString(BackgroundJob.JOB_SITEKEY);
            if (created == null && beginTime != null) {
                // this can happen for cron scheduler jobs.
                created = new Date(beginTime);
            }
            Long duration = getLong(jobDataMap, BackgroundJob.JOB_DURATION);
            if ((duration == null) && (beginTime != null) && (endTime == null)
                    && BackgroundJob.STATUS_EXECUTING.equals(status)) {
                // here we have a currently running job, let's calculate the duration until now.
                duration = System.currentTimeMillis() - beginTime.longValue();
            }
            final String jobLocale = jobDataMap.getString(BackgroundJob.JOB_CURRENT_LOCALE);
            String targetNodeIdentifier = null;
            String targetAction = null;
            String targetWorkspace = null;

            //            if ((jahiaUser != null) && (!jahiaUser.getUserKey().equals(user))) {
            // we must check whether the user has the permission to view other users's jobs
            //                if (!jahiaUser.isPermitted(new PermissionIdentity("view-all-jobs"))) {
            //                    // he doesn't we skip this entry.
            //                    continue;
            //                }
            //            }

            String description = jobDetail.getDescription();
            final List<String> targetPaths = new ArrayList<String>();
            String fileName = jobDataMap.getString(ImportJob.FILENAME);
            if (BackgroundJob.getGroupName(PublicationJob.class).equals(jobDetail.getGroup())) {
                @SuppressWarnings("unchecked")
                List<GWTJahiaNodeProperty> publicationInfos = (List<GWTJahiaNodeProperty>) jobDataMap
                        .get(PublicationJob.PUBLICATION_PROPERTIES);
                if (publicationInfos != null && publicationInfos.size() > 0) {
                    description += " " + publicationInfos.get(0).getValues();
                }
                List<String> publicationPathsFromJob = (List<String>) jobDataMap
                        .get(PublicationJob.PUBLICATION_PATHS);
                // get target paths from job if specified, if not, use uuids to get the nodes
                if (publicationPathsFromJob != null && publicationPathsFromJob.size() > 0) {
                    targetPaths.addAll(publicationPathsFromJob);
                } else {
                    final List<String> uuids = (List<String>) jobDataMap.get("publicationInfos");
                    try {
                        JCRTemplate.getInstance().doExecuteWithSystemSession(new JCRCallback<Object>() {
                            @Override
                            public Object doInJCR(JCRSessionWrapper session) throws RepositoryException {
                                for (String uuid : uuids) {
                                    try {
                                        targetPaths.add(session.getNodeByIdentifier(uuid).getPath());
                                    } catch (ItemNotFoundException e) {
                                        logger.debug("Cannot get item " + uuid, e);
                                    }
                                }
                                return null;
                            }
                        });
                    } catch (RepositoryException e) {
                        logger.error("Cannot get publication details", e);
                    }
                }
            } else if (BackgroundJob.getGroupName(ImportJob.class).equals(jobDetail.getGroup())) {
                String uri = (String) jobDataMap.get(ImportJob.URI);
                if (uri != null) {
                    targetPaths.add(uri);
                    description += " " + uri;
                } else {
                    String destinationParentPath = jobDataMap.getString(ImportJob.DESTINATION_PARENT_PATH);
                    targetPaths.add(destinationParentPath);
                }
            } else if (BackgroundJob.getGroupName(ActionJob.class).equals(jobDetail.getGroup())) {
                String actionToExecute = jobDataMap.getString(ActionJob.JOB_ACTION_TO_EXECUTE);
                targetAction = actionToExecute;
                String nodeUUID = jobDataMap.getString(ActionJob.JOB_NODE_UUID);
                targetNodeIdentifier = nodeUUID;
            } else if (BackgroundJob.getGroupName(RuleJob.class).equals(jobDetail.getGroup())) {
                String ruleToExecute = jobDataMap.getString(RuleJob.JOB_RULE_TO_EXECUTE);
                targetAction = ruleToExecute;
                String nodeUUID = jobDataMap.getString(RuleJob.JOB_NODE_UUID);
                targetNodeIdentifier = nodeUUID;
                String workspace = jobDataMap.getString(RuleJob.JOB_WORKSPACE);
                targetWorkspace = workspace;
            } else if (BackgroundJob.getGroupName(TextExtractorJob.class).equals(jobDetail.getGroup())) {
                String path = jobDataMap.getString(TextExtractorJob.JOB_PATH);
                String extractNodePath = jobDataMap.getString(TextExtractorJob.JOB_EXTRACTNODE_PATH);
                targetPaths.add(path);
                targetPaths.add(extractNodePath);
            }
            GWTJahiaJobDetail job = new GWTJahiaJobDetail(jobDetail.getName(), created, user, site, description,
                    status, message, targetPaths, jobDetail.getGroup(), jobDetail.getJobClass().getName(),
                    beginTime, endTime, duration, jobLocale, fileName, targetNodeIdentifier, targetAction,
                    targetWorkspace);
            job.setLabelKey("label." + jobDetail.getGroup() + ".task");
            jobs.add(job);
        }
        return jobs;
    }

    public List<GWTJahiaJobDetail> getActiveJobs(Locale locale) throws GWTJahiaServiceException {
        try {
            List<JobDetail> l = scheduler.getAllActiveJobs();
            return convertToGWTJobs(l);
        } catch (Exception e) {
            throw new GWTJahiaServiceException("Error retrieving active jobs", e);
        }
    }

    public List<GWTJahiaJobDetail> getAllJobs(Locale locale, JahiaUser jahiaUser, Set<String> groupNames)
            throws GWTJahiaServiceException {
        try {
            List<JobDetail> jobDetails = null;
            if (groupNames == null) {
                jobDetails = scheduler.getAllJobs();
            } else {
                jobDetails = new ArrayList<JobDetail>();
                for (String groupName : groupNames) {
                    jobDetails.addAll(scheduler.getAllJobs(groupName));
                }
            }
            List<GWTJahiaJobDetail> gwtJobList = convertToGWTJobs(jobDetails);
            // do an inverse sort.
            Collections.sort(gwtJobList, JOB_COMPARATOR);
            return gwtJobList;
        } catch (Exception e) {
            throw new GWTJahiaServiceException("Cannot retrieve jobs. Cause: " + e.getLocalizedMessage(), e);
        }

    }

    public Boolean deleteJob(String jobName, String groupName) throws GWTJahiaServiceException {
        try {
            return scheduler.getScheduler().deleteJob(jobName, groupName);
        } catch (SchedulerException e) {
            throw new GWTJahiaServiceException(
                    "Cannot delete job " + jobName + ". Cause: " + e.getLocalizedMessage(), e);
        }
    }

    public List<String> getAllJobGroupNames() throws GWTJahiaServiceException {
        try {
            return Arrays.asList(scheduler.getScheduler().getJobGroupNames());
        } catch (SchedulerException e) {
            throw new GWTJahiaServiceException("Cannot get all job group names. Cause: " + e.getLocalizedMessage(),
                    e);
        }
    }

    public Integer deleteAllCompletedJobs() throws GWTJahiaServiceException {
        try {
            return scheduler.deleteAllCompletedJobs();
        } catch (SchedulerException e) {
            throw new GWTJahiaServiceException("Cannot delete completed jobs. Cause: " + e.getLocalizedMessage(),
                    e);
        }
    }

    class PollingSchedulerListener extends JobListenerSupport {
        int totalCount = -1;

        public String getName() {
            return "PollingSchedulerListener";
        }

        @Override
        public void jobToBeExecuted(JobExecutionContext context) {
            updateJobs(Arrays.asList(context.getJobDetail()), Collections.<JobDetail>emptyList());
        }

        @Override
        public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
            updateJobs(Collections.<JobDetail>emptyList(), Arrays.asList(context.getJobDetail()));
        }

        private void updateJobs(List<JobDetail> startedJob, List<JobDetail> endedJob) {
            try {
                if (totalCount == -1) {
                    totalCount = getActiveJobs(Locale.ENGLISH).size();
                } else {
                    totalCount += startedJob.size();
                }
                totalCount -= endedJob.size();
                if (totalCount < 0) {
                    //In case job is ended only and there is no active nor started job
                    totalCount = 0;
                }
                final BroadcasterFactory broadcasterFactory = AtmosphereServlet.getBroadcasterFactory();
                if (broadcasterFactory != null) {
                    ProcessPollingEvent pollingEvent = new ProcessPollingEvent();
                    if (startedJob != null) {
                        pollingEvent.setStartedJob(convertToGWTJobs(startedJob));
                    }
                    if (endedJob != null) {
                        pollingEvent.setEndedJob(convertToGWTJobs(endedJob));
                    }
                    pollingEvent.setTotalCount(totalCount);
                    Broadcaster broadcaster = broadcasterFactory.lookup(ManagedGWTResource.GWT_BROADCASTER_ID);
                    if (broadcaster != null) {
                        broadcaster.broadcast(pollingEvent);
                    } else {
                        try {
                            ChannelHolder bean = (ChannelHolder) SpringContextSingleton
                                    .getBean("org.jahia.ajax.gwt.commons.server.ChannelHolderImpl");
                            JGroupsChannel jc = bean.getChannel();
                            if (jc != null) {
                                jc.send(ManagedGWTResource.GWT_BROADCASTER_ID, pollingEvent);
                            }
                        } catch (Exception e) {
                            logger.debug(e.getMessage(), e);
                        }
                    }
                }
            } catch (GWTJahiaServiceException e) {
                logger.error("Cannot parse jobs", e);
            }

        }
    }

}