001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.scheduler.jobs;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsProject;
032import org.opencms.file.CmsUser;
033import org.opencms.lock.CmsLock;
034import org.opencms.main.CmsException;
035import org.opencms.main.CmsLog;
036import org.opencms.main.OpenCms;
037import org.opencms.notification.CmsPublishNotification;
038import org.opencms.report.CmsWorkplaceReport;
039import org.opencms.scheduler.CmsScheduledJobInfo;
040import org.opencms.scheduler.I_CmsScheduledJob;
041
042import java.text.DateFormat;
043import java.util.Date;
044import java.util.Iterator;
045import java.util.Map;
046
047import org.apache.commons.logging.Log;
048
049/**
050 * Scheduled job for time based publishing.<p>
051 *
052 * This class is called via the front end to publish scheduled a file at a given time.<p>
053 *
054 * Per default, it publishes all new, edited and deleted resources in the project which are locked in
055 * the current project. For all resources in the project which are not locked by the current user is the
056 * lock changed. You are able to perform a link validation before
057 * publishing the project by adding the parameter <code>linkcheck=true</code>. It is possible to send
058 * an email to a user in OpenCms in case somthing went wrong during this process. To do so specifiy
059 * a parameter<code>mail-to-user=username_in_opencms</code>.
060 * After running this job, the job is deleted. Therefore the job name is to set in the parameter <code>jobname</code><p>
061 *
062 * @since 7.5.1
063 */
064public class CmsPublishScheduledJob implements I_CmsScheduledJob {
065
066    /** Job name parameter. */
067    public static final String PARAM_JOBNAME = "jobname";
068
069    /** Linkcheck parameter. */
070    public static final String PARAM_LINKCHECK = "linkcheck";
071
072    /** Mail to user parameter. */
073    public static final String PARAM_USER = "mail-to-user";
074
075    /** The log object for this class. */
076    private static final Log LOG = CmsLog.getLog(CmsPublishScheduledJob.class);
077
078    /**
079     * @see org.opencms.scheduler.I_CmsScheduledJob#launch(org.opencms.file.CmsObject, java.util.Map)
080     */
081    public synchronized String launch(CmsObject cms, Map<String, String> parameters) throws Exception {
082
083        Date jobStart = new Date();
084        String finishMessage;
085        String linkcheck = parameters.get(PARAM_LINKCHECK);
086        String jobName = parameters.get(PARAM_JOBNAME);
087        CmsProject project = cms.getRequestContext().getCurrentProject();
088        CmsWorkplaceReport report = new CmsWorkplaceReport(
089            cms.getRequestContext().getLocale(),
090            cms.getRequestContext().getSiteRoot(),
091            CmsPublishScheduledJob.class);
092
093        try {
094
095            // validate links if linkcheck parameter was given
096            if (Boolean.valueOf(linkcheck).booleanValue()) {
097                OpenCms.getPublishManager().validateRelations(
098                    cms,
099                    OpenCms.getPublishManager().getPublishList(cms),
100                    report);
101            }
102
103            // change lock for the resources if necessary
104            Iterator<String> iter = cms.readProjectResources(project).iterator();
105            while (iter.hasNext()) {
106                String resource = iter.next();
107                // get current lock from file
108                CmsLock lock = cms.getLock(resource);
109                // prove is current lock from current but not in current project
110                if ((lock != null)
111                    && lock.isInProject(cms.getRequestContext().getCurrentProject())
112                    && !lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) {
113                    // file is locked in current project but not by current user
114                    // unlock this file
115                    cms.changeLock(resource);
116                }
117            }
118
119            // publish the project, the publish output will be put in the logfile
120            OpenCms.getPublishManager().publishProject(cms, report);
121            OpenCms.getPublishManager().waitWhileRunning();
122            finishMessage = Messages.get().getBundle().key(Messages.LOG_PUBLISH_FINISHED_1, project.getName());
123        } catch (CmsException e) {
124            // there was an error, so create an output for the logfile
125            finishMessage = Messages.get().getBundle().key(
126                Messages.LOG_PUBLISH_FAILED_2,
127                project.getName(),
128                e.getMessageContainer().key());
129
130            // add error to report
131            report.addError(finishMessage);
132        } finally {
133            //wait for other processes that may add entries to the report
134            long lastTime = report.getLastEntryTime();
135            long beforeLastTime = 0;
136            while (lastTime != beforeLastTime) {
137                wait(30000);
138                beforeLastTime = lastTime;
139                lastTime = report.getLastEntryTime();
140            }
141
142            // delete the job
143            // the job id
144            String jobId = "";
145            // iterate over all jobs to find the current one
146            Iterator<CmsScheduledJobInfo> iter = OpenCms.getScheduleManager().getJobs().iterator();
147            while (iter.hasNext()) {
148                CmsScheduledJobInfo jobInfo = iter.next();
149                // the current job is found with the job name
150                if (jobInfo.getJobName().equals(jobName)) {
151                    // get the current job id
152                    jobId = jobInfo.getId();
153                }
154            }
155            // delete the current job
156            OpenCms.getScheduleManager().unscheduleJob(cms, jobId);
157
158            // send publish notification
159            if (report.hasWarning() || report.hasError()) {
160                try {
161                    String userName = parameters.get(PARAM_USER);
162                    CmsUser user = cms.readUser(userName);
163
164                    CmsPublishNotification notification = new CmsPublishNotification(cms, user, report);
165
166                    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
167                    notification.addMacro("jobStart", df.format(jobStart));
168
169                    notification.send();
170                } catch (Exception e) {
171                    LOG.error(Messages.get().getBundle().key(Messages.LOG_PUBLISH_SEND_NOTIFICATION_FAILED_0), e);
172                }
173            }
174        }
175
176        return finishMessage;
177    }
178}