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.workplace.commons;
029
030import org.opencms.configuration.CmsSchedulerConfiguration;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsProject;
033import org.opencms.file.CmsResource;
034import org.opencms.jsp.CmsJspActionElement;
035import org.opencms.lock.CmsLock;
036import org.opencms.main.CmsContextInfo;
037import org.opencms.main.CmsException;
038import org.opencms.main.OpenCms;
039import org.opencms.scheduler.CmsScheduledJobInfo;
040import org.opencms.scheduler.jobs.CmsPublishScheduledJob;
041import org.opencms.security.CmsAccessControlEntry;
042import org.opencms.security.CmsPermissionSet;
043import org.opencms.security.CmsRole;
044import org.opencms.util.CmsDateUtil;
045import org.opencms.util.CmsStringUtil;
046import org.opencms.util.CmsUUID;
047import org.opencms.workplace.CmsDialog;
048import org.opencms.workplace.CmsWorkplace;
049import org.opencms.workplace.CmsWorkplaceAction;
050import org.opencms.workplace.CmsWorkplaceSettings;
051
052import java.text.DateFormat;
053import java.text.ParseException;
054import java.util.Calendar;
055import java.util.Date;
056import java.util.SortedMap;
057import java.util.TreeMap;
058
059import javax.servlet.http.HttpServletRequest;
060import javax.servlet.http.HttpServletResponse;
061import javax.servlet.jsp.JspException;
062import javax.servlet.jsp.PageContext;
063
064/**
065 * Provides methods for the publish scheduled dialog.<p>
066 *
067 * The following files use this class:
068 * <ul>
069 * <li>/commons/publishscheduled.jsp
070 * </ul>
071 * <p>
072 *
073 * @since 7.5.1
074 */
075public class CmsPublishScheduled extends CmsDialog {
076
077    /** The dialog type. */
078    public static final String DIALOG_TYPE = "publishscheduled";
079
080    /** Request parameter name for the activation of the notification. */
081    public static final String PARAM_ENABLE_NOTIFICATION = "enablenotification";
082
083    /** Request parameter name for the publish date. */
084    public static final String PARAM_PUBLISHSCHEDULEDDATE = "publishscheduleddate";
085
086    /** Request parameter name for the reset publish date. */
087    public static final String PARAM_RESETPUBLISHSCHEDULED = "resetpublishscheduled";
088
089    /** The parameter for publish scheduled date. */
090    private String m_paramPublishscheduleddate;
091
092    /**
093     * Public constructor.<p>
094     *
095     * @param jsp an initialized JSP action element
096     */
097    public CmsPublishScheduled(CmsJspActionElement jsp) {
098
099        super(jsp);
100    }
101
102    /**
103     * Public constructor with JSP variables.<p>
104     *
105     * @param context the JSP page context
106     * @param req the JSP request
107     * @param res the JSP response
108     */
109    public CmsPublishScheduled(PageContext context, HttpServletRequest req, HttpServletResponse res) {
110
111        this(new CmsJspActionElement(context, req, res));
112    }
113
114    /**
115     *
116     * @see org.opencms.workplace.CmsDialog#actionCloseDialog()
117     */
118    @Override
119    public void actionCloseDialog() throws JspException {
120
121        // so that the explorer will be shown, if dialog is opened from e-mail
122        getSettings().getFrameUris().put("body", CmsWorkplace.VFS_PATH_VIEWS + "explorer/explorer_fs.jsp");
123        super.actionCloseDialog();
124    }
125
126    /**
127     * Performs the resource operation, will be called by the JSP page.<p>
128     *
129     * @throws JspException if problems including sub-elements occur
130     */
131    public void actionUpdate() throws JspException {
132
133        // save initialized instance of this class in request attribute for included sub-elements
134        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this);
135
136        try {
137            // prepare the publish scheduled resource
138            performDialogOperation();
139            // close the dialog
140            actionCloseDialog();
141        } catch (Throwable e) {
142            // show the error page
143            includeErrorpage(this, e);
144        }
145    }
146
147    /**
148     * Returns the value of the publish scheduled date.<p>
149     *
150     * @return the value of the publish scheduled date
151     */
152    public String getParamPublishscheduleddate() {
153
154        return m_paramPublishscheduleddate;
155    }
156
157    /**
158     * Sets the title of the dialog.<p>
159     *
160     * @param singleKey the key for the single operation
161     */
162    public void setDialogTitle(String singleKey) {
163
164        // generate title using the resource name as parameter for the key
165        String resourceName = CmsStringUtil.formatResourceName(getParamResource(), 50);
166        setParamTitle(key(singleKey, new Object[] {resourceName}));
167    }
168
169    /**
170     * Sets the value of the reset expire parameter.<p>
171     *
172     * @param paramPublishscheduleddate the value of the publish scheduled date
173     */
174    public void setParamPublishscheduleddate(String paramPublishscheduleddate) {
175
176        m_paramPublishscheduleddate = paramPublishscheduleddate;
177    }
178
179    /**
180     * Creates the publish project's name for a given root path and publish date.<p>
181     *
182     * @param rootPath the publish resource's root path
183     * @param date the publish date
184     *
185     * @return the publish project name
186     */
187    protected String computeProjectName(String rootPath, Date date) {
188
189        // create the temporary project, which is deleted after publishing
190        // the publish scheduled date in project name
191        String dateTime = CmsDateUtil.getDateTime(date, DateFormat.SHORT, getLocale());
192        // the resource name to publish scheduled
193        String projectName = key(Messages.GUI_PUBLISH_SCHEDULED_PROJECT_NAME_2, new Object[] {rootPath, dateTime});
194        // the HTML encoding for slashes is necessary because of the slashes in english date time format
195        // in project names slahes are not allowed, because these are separators for organizaional units
196        projectName = projectName.replace("/", "&#47;");
197        return projectName;
198    }
199
200    /**
201     * Returns a localized String for "Group", if the flag of a group ACE, and the localization for "User" otherwise.<p>
202     *
203     * @param flags the flags of the ACE
204     *
205     * @return localization for "Group", if the flag belongs to a group ACE
206     */
207    protected String getLocalizedType(int flags) {
208
209        if ((flags & CmsAccessControlEntry.ACCESS_FLAGS_USER) > 0) {
210            return key(Messages.GUI_LABEL_USER_0);
211        } else {
212            return key(Messages.GUI_LABEL_GROUP_0);
213        }
214    }
215
216    /**
217     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
218     */
219    @Override
220    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
221
222        // fill the parameter values in the get/set methods
223        fillParamValues(request);
224
225        // check the required permissions to modify the resource
226        if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) {
227            // no write permissions for the resource, set cancel action to close dialog
228            setParamAction(DIALOG_CANCEL);
229        }
230
231        // set the dialog type
232        setParamDialogtype(DIALOG_TYPE);
233
234        // set the action for the JSP switch
235        if (DIALOG_TYPE.equals(getParamAction())) {
236            setAction(ACTION_OK);
237        } else if (DIALOG_WAIT.equals(getParamAction())) {
238            setAction(ACTION_WAIT);
239        } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) {
240            setAction(ACTION_LOCKS_CONFIRMED);
241        } else if (DIALOG_CANCEL.equals(getParamAction())) {
242            setAction(ACTION_CANCEL);
243        } else {
244            setAction(ACTION_DEFAULT);
245            // build title for dialog
246            setDialogTitle(Messages.GUI_PUBLISH_SCHEDULED_SETTINGS_1);
247        }
248    }
249
250    /**
251     * Modifies the time shift publish date of a resource. <p>
252     *
253     * @return true, if the operation was performed, otherwise false
254     *
255     * @throws CmsException if something goes wrong
256     * @throws ParseException if something goes wrong
257     */
258    protected boolean performDialogOperation() throws CmsException, ParseException {
259
260        // get the request parameters for resource and publish scheduled date
261        String resource = getParamResource();
262        String publishScheduledDate = getParamPublishscheduleddate();
263        String userName = getCms().getRequestContext().getCurrentUser().getName();
264
265        // get the java date format
266        //        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale());
267        //        dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
268        //        Date date = dateFormat.parse(publishScheduledDate);
269        long lDate = org.opencms.widgets.CmsCalendarWidget.getCalendarDate(getMessages(), publishScheduledDate, true);
270        Date date = new Date(lDate);
271
272        // check if the selected date is in the future
273        if (date.getTime() < new Date().getTime()) {
274            // the selected date in in the past, this is not possible
275            throw new CmsException(Messages.get().container(Messages.ERR_PUBLISH_SCHEDULED_DATE_IN_PAST_1, date));
276        }
277
278        // make copies from the admin cmsobject and the user cmsobject
279        // get the admin cms object
280        CmsWorkplaceAction action = CmsWorkplaceAction.getInstance();
281        CmsObject cmsAdmin = action.getCmsAdminObject();
282        // get the user cms object
283        CmsObject cms = OpenCms.initCmsObject(getCms());
284
285        // set the current user site to the admin cms object
286        cmsAdmin.getRequestContext().setSiteRoot(cms.getRequestContext().getSiteRoot());
287
288        String rootPath = getCms().getRequestContext().addSiteRoot(resource);
289        String projectName = computeProjectName(rootPath, date);
290        CmsProject tmpProject = null;
291        try {
292            // create the project
293            tmpProject = cmsAdmin.createProject(
294                projectName,
295                "",
296                CmsRole.WORKPLACE_USER.getGroupName(),
297                CmsRole.PROJECT_MANAGER.getGroupName(),
298                CmsProject.PROJECT_TYPE_TEMPORARY);
299        } catch (CmsException e) {
300            String resName = CmsResource.getName(rootPath);
301            if (resName.length() > 64) {
302                resName = resName.substring(0, 64) + "...";
303            }
304            // use UUID to make sure the project name is still unique
305            projectName = computeProjectName(resName, date) + " [" + new CmsUUID() + "]";
306            // create the project
307            tmpProject = cmsAdmin.createProject(
308                projectName,
309                "",
310                CmsRole.WORKPLACE_USER.getGroupName(),
311                CmsRole.PROJECT_MANAGER.getGroupName(),
312                CmsProject.PROJECT_TYPE_TEMPORARY);
313        }
314        // make the project invisible for all users
315        tmpProject.setHidden(true);
316        // write the project to the database
317        cmsAdmin.writeProject(tmpProject);
318        // set project as current project
319        cmsAdmin.getRequestContext().setCurrentProject(tmpProject);
320        cms.getRequestContext().setCurrentProject(tmpProject);
321
322        // copy the resource to the project
323        cmsAdmin.copyResourceToProject(resource);
324
325        // lock the resource in the current project
326        CmsLock lock = cms.getLock(resource);
327        // prove is current lock from current but not in current project
328        if ((lock != null)
329            && lock.isOwnedBy(cms.getRequestContext().getCurrentUser())
330            && !lock.isOwnedInProjectBy(
331                cms.getRequestContext().getCurrentUser(),
332                cms.getRequestContext().getCurrentProject())) {
333            // file is locked by current user but not in current project
334            // change the lock from this file
335            cms.changeLock(resource);
336        }
337        // lock resource from current user in current project
338        cms.lockResource(resource);
339        // get current lock
340        lock = cms.getLock(resource);
341
342        // create a new scheduled job
343        CmsScheduledJobInfo job = new CmsScheduledJobInfo();
344        // the job name
345        String jobName = projectName;
346        // set the job parameters
347        job.setJobName(jobName);
348        job.setClassName("org.opencms.scheduler.jobs.CmsPublishScheduledJob");
349        // create the cron expression
350        Calendar calendar = Calendar.getInstance();
351        calendar.setTime(date);
352        String cronExpr = ""
353            + calendar.get(Calendar.SECOND)
354            + " "
355            + calendar.get(Calendar.MINUTE)
356            + " "
357            + calendar.get(Calendar.HOUR_OF_DAY)
358            + " "
359            + calendar.get(Calendar.DAY_OF_MONTH)
360            + " "
361            + (calendar.get(Calendar.MONTH) + 1)
362            + " "
363            + "?"
364            + " "
365            + calendar.get(Calendar.YEAR);
366        // set the cron expression
367        job.setCronExpression(cronExpr);
368        // set the job active
369        job.setActive(true);
370        // create the context info
371        CmsContextInfo contextInfo = new CmsContextInfo();
372        contextInfo.setProjectName(projectName);
373        contextInfo.setUserName(cmsAdmin.getRequestContext().getCurrentUser().getName());
374        // create the job schedule parameter
375        SortedMap<String, String> params = new TreeMap<String, String>();
376        // the user to send mail to
377        params.put(CmsPublishScheduledJob.PARAM_USER, userName);
378        // the job name
379        params.put(CmsPublishScheduledJob.PARAM_JOBNAME, jobName);
380        // the link check
381        params.put(CmsPublishScheduledJob.PARAM_LINKCHECK, "true");
382        // add the job schedule parameter
383        job.setParameters(params);
384        // add the context info to the scheduled job
385        job.setContextInfo(contextInfo);
386        // add the job to the scheduled job list
387        OpenCms.getScheduleManager().scheduleJob(cmsAdmin, job);
388        // update the XML configuration
389        OpenCms.writeConfiguration(CmsSchedulerConfiguration.class);
390        return true;
391    }
392}