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.file.CmsGroup;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsProperty;
033import org.opencms.file.CmsPropertyDefinition;
034import org.opencms.file.CmsResource;
035import org.opencms.file.CmsResourceFilter;
036import org.opencms.jsp.CmsJspActionElement;
037import org.opencms.lock.CmsLockActionRecord;
038import org.opencms.lock.CmsLockActionRecord.LockChange;
039import org.opencms.lock.CmsLockUtil;
040import org.opencms.main.CmsException;
041import org.opencms.main.CmsIllegalArgumentException;
042import org.opencms.main.CmsLog;
043import org.opencms.main.OpenCms;
044import org.opencms.security.CmsAccessControlEntry;
045import org.opencms.security.CmsPermissionSet;
046import org.opencms.security.I_CmsPrincipal;
047import org.opencms.util.CmsStringUtil;
048import org.opencms.widgets.CmsCalendarWidget;
049import org.opencms.workplace.CmsMultiDialog;
050import org.opencms.workplace.CmsWorkplace;
051import org.opencms.workplace.CmsWorkplaceSettings;
052
053import java.text.ParseException;
054import java.util.ArrayList;
055import java.util.Collection;
056import java.util.HashMap;
057import java.util.Iterator;
058import java.util.List;
059import java.util.Map;
060
061import javax.servlet.http.HttpServletRequest;
062import javax.servlet.http.HttpServletResponse;
063import javax.servlet.jsp.JspException;
064import javax.servlet.jsp.PageContext;
065
066import org.apache.commons.logging.Log;
067
068/**
069 * Provides methods for the resource availability/notification dialog.<p>
070 *
071 * The following files use this class:
072 * <ul>
073 * <li>/commons/availability.jsp
074 * </ul>
075 * <p>
076 *
077 * @since 6.0.0
078 */
079public class CmsAvailability extends CmsMultiDialog {
080
081    /** The dialog type. */
082    public static final String DIALOG_TYPE = "availability";
083
084    /** Request parameter name for the activation of the notification. */
085    public static final String PARAM_ENABLE_NOTIFICATION = "enablenotification";
086
087    /** Request parameter name for the expire date. */
088    public static final String PARAM_EXPIREDATE = "expiredate";
089
090    /** Request parameter name for the leave expire. */
091    public static final String PARAM_LEAVEEXPIRE = "leaveexpire";
092
093    /** Request parameter name for the leave release. */
094    public static final String PARAM_LEAVERELEASE = "leaverelease";
095
096    /** Request parameter name for the include siblings flag. */
097    public static final String PARAM_MODIFY_SIBLINGS = "modifysiblings";
098
099    /** Request parameter name for the activation of the notification. */
100    public static final String PARAM_NOTIFICATION_INTERVAL = "notificationinterval";
101
102    /** Request parameter name for the recursive flag. */
103    public static final String PARAM_RECURSIVE = "recursive";
104
105    /** Request parameter name for the release date. */
106    public static final String PARAM_RELEASEDATE = "releasedate";
107
108    /** Request parameter name for the reset expire. */
109    public static final String PARAM_RESETEXPIRE = "resetexpire";
110
111    /** Request parameter name for the reset release. */
112    public static final String PARAM_RESETRELEASE = "resetrelease";
113
114    /** The log object for this class. */
115    private static final Log LOG = CmsLog.getLog(CmsAvailability.class);
116
117    /** A parameter of this dialog. */
118    private String m_paramEnablenotification;
119
120    /** A parameter of this dialog. */
121    private String m_paramExpiredate;
122
123    /** A parameter of this dialog. */
124    private String m_paramLeaveexpire;
125
126    /** A parameter of this dialog. */
127    private String m_paramModifysiblings;
128
129    /** A parameter of this dialog. */
130    private String m_paramNotificationinterval;
131
132    /** A parameter of this dialog. */
133    private String m_paramRecursive;
134
135    /** A parameter of this dialog. */
136    private String m_paramReleasedate;
137
138    /** A parameter of this dialog. */
139    private String m_paramResetexpire;
140
141    /** A parameter of this dialog. */
142    private String m_paramResetrelease;
143
144    /**
145     * Public constructor.<p>
146     *
147     * @param jsp an initialized JSP action element
148     */
149    public CmsAvailability(CmsJspActionElement jsp) {
150
151        super(jsp);
152    }
153
154    /**
155     * Public constructor with JSP variables.<p>
156     *
157     * @param context the JSP page context
158     * @param req the JSP request
159     * @param res the JSP response
160     */
161    public CmsAvailability(PageContext context, HttpServletRequest req, HttpServletResponse res) {
162
163        this(new CmsJspActionElement(context, req, res));
164    }
165
166    /**
167     * Performs the notification operations on a single resource.<p>
168     *
169     * @param cms the CMS context
170     * @param resName the VFS path of the resource
171     * @param enableNotification if the notification is activated
172     * @param notificationInterval the notification interval in days
173     * @param modifySiblings flag indicating to include resource siblings
174     *
175     * @throws CmsException if the availability and notification operations fail
176     */
177    public static void performSingleResourceNotification(
178        CmsObject cms,
179        String resName,
180        boolean enableNotification,
181        int notificationInterval,
182        boolean modifySiblings) throws CmsException {
183
184        List<CmsResource> resources = new ArrayList<CmsResource>();
185        if (modifySiblings) {
186            // modify all siblings of a resource
187            resources = cms.readSiblings(resName, CmsResourceFilter.IGNORE_EXPIRATION);
188        } else {
189            // modify only resource without siblings
190            resources.add(cms.readResource(resName, CmsResourceFilter.IGNORE_EXPIRATION));
191        }
192        Iterator<CmsResource> i = resources.iterator();
193        while (i.hasNext()) {
194            CmsResource resource = i.next();
195            String resourcePath = cms.getRequestContext().removeSiteRoot(resource.getRootPath());
196            // lock resource if auto lock is enabled
197            CmsLockActionRecord lockRecord = CmsLockUtil.ensureLock(cms, resource);
198            try {
199                // write notification settings
200                writeProperty(
201                    cms,
202                    resourcePath,
203                    CmsPropertyDefinition.PROPERTY_NOTIFICATION_INTERVAL,
204                    String.valueOf(notificationInterval));
205                writeProperty(
206                    cms,
207                    resourcePath,
208                    CmsPropertyDefinition.PROPERTY_ENABLE_NOTIFICATION,
209                    String.valueOf(enableNotification));
210            } finally {
211                if (lockRecord.getChange() == LockChange.locked) {
212                    cms.unlockResource(resource);
213                }
214            }
215        }
216    }
217
218    /**
219     * Writes a property value for a resource.<p>
220     *
221     * @param cms the cms context
222     * @param resourcePath the path of the resource
223     * @param propertyName the name of the property
224     * @param propertyValue the new value of the property
225     *
226     * @throws CmsException if something goes wrong
227     */
228    public static void writeProperty(CmsObject cms, String resourcePath, String propertyName, String propertyValue)
229    throws CmsException {
230
231        if (CmsStringUtil.isEmpty(propertyValue)) {
232            propertyValue = CmsProperty.DELETE_VALUE;
233        }
234
235        CmsProperty newProp = new CmsProperty();
236        newProp.setName(propertyName);
237        CmsProperty oldProp = cms.readPropertyObject(resourcePath, propertyName, false);
238        if (oldProp.isNullProperty()) {
239            // property value was not already set
240            if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) {
241                newProp.setStructureValue(propertyValue);
242            } else {
243                newProp.setResourceValue(propertyValue);
244            }
245        } else {
246            if (oldProp.getStructureValue() != null) {
247                newProp.setStructureValue(propertyValue);
248                newProp.setResourceValue(oldProp.getResourceValue());
249            } else {
250                newProp.setResourceValue(propertyValue);
251            }
252        }
253
254        newProp.setAutoCreatePropertyDefinition(true);
255
256        String oldStructureValue = oldProp.getStructureValue();
257        String newStructureValue = newProp.getStructureValue();
258        if (CmsStringUtil.isEmpty(oldStructureValue)) {
259            oldStructureValue = CmsProperty.DELETE_VALUE;
260        }
261        if (CmsStringUtil.isEmpty(newStructureValue)) {
262            newStructureValue = CmsProperty.DELETE_VALUE;
263        }
264
265        String oldResourceValue = oldProp.getResourceValue();
266        String newResourceValue = newProp.getResourceValue();
267        if (CmsStringUtil.isEmpty(oldResourceValue)) {
268            oldResourceValue = CmsProperty.DELETE_VALUE;
269        }
270        if (CmsStringUtil.isEmpty(newResourceValue)) {
271            newResourceValue = CmsProperty.DELETE_VALUE;
272        }
273
274        // change property only if it has been changed
275        if (!oldResourceValue.equals(newResourceValue) || !oldStructureValue.equals(newStructureValue)) {
276            cms.writePropertyObject(resourcePath, newProp);
277        }
278    }
279
280    /**
281     *
282     * @see org.opencms.workplace.CmsDialog#actionCloseDialog()
283     */
284    @Override
285    public void actionCloseDialog() throws JspException {
286
287        // so that the explorer will be shown, if dialog is opened from e-mail
288        getSettings().getFrameUris().put("body", CmsWorkplace.VFS_PATH_VIEWS + "explorer/explorer_fs.jsp");
289        super.actionCloseDialog();
290    }
291
292    /**
293     * Performs the resource operation, will be called by the JSP page.<p>
294     *
295     * @throws JspException if problems including sub-elements occur
296     */
297    public void actionUpdate() throws JspException {
298
299        // save initialized instance of this class in request attribute for included sub-elements
300        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this);
301
302        try {
303            if (performDialogOperation()) {
304                // if no exception is caused and "true" is returned the dialog operation was successful
305                actionCloseDialog();
306            } else {
307                // "false" returned, display "please wait" screen
308                getJsp().include(FILE_DIALOG_SCREEN_WAIT);
309            }
310        } catch (Throwable e) {
311            includeErrorpage(this, e);
312        }
313    }
314
315    /**
316     * Creates the check box to enable content notification for a resource.<p>
317     *
318     * @return HTML code for the enable_notification check box.
319     */
320    public String buildCheckboxEnableNotification() {
321
322        String propVal = null;
323        if (!isMultiOperation()) {
324            // get current settings for single resource dialog
325            try {
326                propVal = getCms().readPropertyObject(
327                    getParamResource(),
328                    CmsPropertyDefinition.PROPERTY_ENABLE_NOTIFICATION,
329                    false).getValue();
330            } catch (CmsException e) {
331                if (LOG.isInfoEnabled()) {
332                    LOG.info(e.getLocalizedMessage());
333                }
334            }
335
336        }
337        if (CmsStringUtil.isEmpty(propVal)) {
338            propVal = CmsStringUtil.FALSE;
339        }
340        StringBuffer result = new StringBuffer(512);
341        result.append("<input type=\"checkbox\" style=\"text-align:left\" name=\"");
342        result.append(PARAM_ENABLE_NOTIFICATION);
343        if (Boolean.valueOf(propVal).booleanValue()) {
344            result.append("\" checked=\"checked");
345        }
346        result.append("\" value=\"true\">");
347        return result.toString();
348    }
349
350    /**
351     * Creates an the check box to modify all siblings.<p>
352     *
353     * If no siblings exist for this resource, an empty string will be returned.
354     *
355     * @return HTML code for the modify siblings check box.
356     */
357    public String buildCheckboxModifySiblings() {
358
359        StringBuffer result = new StringBuffer(254);
360        try {
361            if (isMultiOperation() || (getCms().readSiblings(getParamResource(), CmsResourceFilter.ALL).size() > 1)) {
362                result.append("<tr>\n<td style=\"white-space:nowrap;\">");
363                result.append(key(Messages.GUI_AVAILABILITY_MODIFY_SIBLINGS_0));
364                result.append("</td>\n<td class=\"maxwidth\" style=\"padding-left: 5px;\">\n");
365                result.append("<input type=\"checkbox\" name=\"");
366                result.append(PARAM_MODIFY_SIBLINGS);
367                result.append("\" value=\"true\" style=\"text-align:left\">\n</td>\n<td>&nbsp</td></tr>");
368            }
369        } catch (CmsException e) {
370            if (LOG.isInfoEnabled()) {
371                LOG.info(e.getLocalizedMessage(), e);
372            }
373        }
374        return result.toString();
375    }
376
377    /**
378     * Creates the "recursive" check box for touching subresources of folders.<p>
379     *
380     * @return the String with the check box input field or an empty String for folders.
381     */
382    public String buildCheckRecursive() {
383
384        StringBuffer result = new StringBuffer(256);
385
386        // show the check box only for operation(s) on folder(s)
387        if (isOperationOnFolder()) {
388            result.append(dialogBlockStart(key(Messages.GUI_AVAILABILITY_NOTIFICATION_SUBRES_0)));
389            result.append("<table border=\"0\">");
390            result.append("<tr>\n\t<td style=\"white-space:nowrap;\">");
391            result.append(key(Messages.GUI_TOUCH_MODIFY_SUBRESOURCES_0));
392            result.append(
393                "</td><td class=\"maxwidth\" style=\"padding-left: 5px;\"><input type=\"checkbox\" style=\"text-align:left\" name=\"");
394            result.append(PARAM_RECURSIVE);
395            result.append("\" value=\"true\">&nbsp;</td>\n<td>&nbsp</td></tr>\n");
396            result.append("</table>");
397            result.append(dialogBlockEnd());
398            result.append(dialogSpacer());
399        }
400        return result.toString();
401    }
402
403    /**
404     * Creates an input field for the notification interval.<p>
405     *
406     * @return HTML code for the notification interval input field.
407     */
408    public String buildInputNotificationInterval() {
409
410        String propVal = null;
411        if (!isMultiOperation()) {
412            try {
413                propVal = getCms().readPropertyObject(
414                    getParamResource(),
415                    CmsPropertyDefinition.PROPERTY_NOTIFICATION_INTERVAL,
416                    false).getValue();
417            } catch (CmsException e) {
418                if (LOG.isInfoEnabled()) {
419                    LOG.info(e.getLocalizedMessage());
420                }
421            }
422        }
423        if (CmsStringUtil.isEmpty(propVal)) {
424            propVal = "";
425        }
426        StringBuffer result = new StringBuffer();
427
428        result.append("<input class=\"maxwidth\" type=\"text\" name=\"");
429        result.append(CmsAvailability.PARAM_NOTIFICATION_INTERVAL);
430        result.append("\" value=\"");
431        result.append(propVal);
432        result.append("\">");
433        return result.toString();
434    }
435
436    /**
437     * Builds a String with HTML code to display the responsibles of a resource.<p>
438     *
439     * @return HTML code for the responsibles of the current resource
440     */
441    public String buildResponsibleList() {
442
443        if (isMultiOperation()) {
444            // show no responsibles list for multi operation
445            return "";
446        } else {
447            // single resource operation, create list of responsibles
448            StringBuffer result = new StringBuffer(512);
449            result.append("<tr><td colspan=\"3\">");
450            List<CmsResource> parentResources = new ArrayList<CmsResource>();
451            Map<I_CmsPrincipal, String> responsibles = new HashMap<I_CmsPrincipal, String>();
452            CmsObject cms = getCms();
453            String resourceSitePath = cms.getRequestContext().removeSiteRoot(getParamResource());
454            try {
455                // get all parent folders of the current file
456                parentResources = cms.readPath(getParamResource(), CmsResourceFilter.IGNORE_EXPIRATION);
457            } catch (CmsException e) {
458                // can usually be ignored
459                if (LOG.isInfoEnabled()) {
460                    LOG.info(e.getLocalizedMessage());
461                }
462            }
463            Iterator<CmsResource> i = parentResources.iterator();
464            while (i.hasNext()) {
465                CmsResource resource = i.next();
466                try {
467                    String sitePath = cms.getRequestContext().removeSiteRoot(resource.getRootPath());
468                    Iterator<CmsAccessControlEntry> entries = cms.getAccessControlEntries(sitePath, false).iterator();
469                    while (entries.hasNext()) {
470                        CmsAccessControlEntry ace = entries.next();
471                        if (ace.isResponsible()) {
472                            I_CmsPrincipal principal = cms.lookupPrincipal(ace.getPrincipal());
473                            if (principal != null) {
474                                responsibles.put(principal, resourceSitePath.equals(sitePath) ? null : sitePath);
475                            }
476                        }
477                    }
478                } catch (CmsException e) {
479                    // can usually be ignored
480                    if (LOG.isInfoEnabled()) {
481                        LOG.info(e.getLocalizedMessage());
482                    }
483                }
484            }
485
486            if (responsibles.size() == 0) {
487                // no responsibles found
488                result.append(key(Messages.GUI_AVAILABILITY_NO_RESPONSIBLES_0));
489            } else {
490                // found responsibles, create list
491                result.append(dialogToggleStart(key(Messages.GUI_AVAILABILITY_RESPONSIBLES_0), "responsibles", false));
492                Collection<String> parentFolders = new ArrayList<String>(responsibles.values());
493                parentFolders.remove(null);
494                if (parentFolders.size() > 0) {
495                    result.append("<table border=\"0\">\n<tr>\n\t<td>");
496                    result.append(key(Messages.GUI_PERMISSION_SELECT_VIEW_0));
497                    result.append("</td>\n<td><input type=\"button\" onclick=\"toggleInheritInfo();\" value=\"");
498                    result.append(key(Messages.GUI_LABEL_DETAILS_0));
499                    result.append("\" id=\"button\"/></td></tr></table>");
500                }
501                result.append(dialogWhiteBoxStart());
502                Iterator<Map.Entry<I_CmsPrincipal, String>> it = responsibles.entrySet().iterator();
503                for (int j = 0; it.hasNext(); j++) {
504                    Map.Entry<I_CmsPrincipal, String> entry = it.next();
505                    I_CmsPrincipal principal = entry.getKey();
506                    String image = "user.png";
507                    String localizedType = getLocalizedType(CmsAccessControlEntry.ACCESS_FLAGS_USER);
508                    if (principal instanceof CmsGroup) {
509                        image = "group.png";
510                        localizedType = getLocalizedType(CmsAccessControlEntry.ACCESS_FLAGS_GROUP);
511                    }
512                    result.append("<div class=\"dialogrow\"><img src=\"");
513                    result.append(getSkinUri());
514                    result.append("commons/");
515                    result.append(image);
516                    result.append("\" class=\"noborder\" width=\"16\" height=\"16\" alt=\"");
517                    result.append(localizedType);
518                    result.append("\" title=\"");
519                    result.append(localizedType);
520                    result.append("\">&nbsp;<span class=\"textbold\">");
521                    result.append(principal.getName());
522                    result.append("</span><div class=\"hide\" id=\"inheritinfo");
523                    result.append(j);
524                    result.append("\"><div class=\"dialogpermissioninherit\">");
525                    String resourceName = entry.getValue();
526                    if (CmsStringUtil.isNotEmpty(resourceName)) {
527                        result.append(key(Messages.GUI_PERMISSION_INHERITED_FROM_1, new Object[] {resourceName}));
528                    }
529                    result.append("</div></div></div>\n");
530                }
531                result.append(dialogWhiteBoxEnd());
532                result.append("</div>\n");
533                result.append("</td></tr>");
534            }
535            return result.toString();
536        }
537    }
538
539    /**
540     * Returns the current date and time as String formatted in localized pattern.<p>
541     *
542     * @return the current date and time as String formatted in localized pattern
543     */
544    public String getCurrentDateTime() {
545
546        // get the current date & time
547        return CmsCalendarWidget.getCalendarLocalizedTime(getLocale(), getMessages(), System.currentTimeMillis());
548    }
549
550    /**
551     * Returns the current expire date as String formatted in localized pattern.<p>
552     *
553     * @return the current expire date as String formatted in localized pattern
554     */
555    public String getCurrentExpireDate() {
556
557        // get the expiration date
558        if (isMultiOperation()) {
559            return CmsTouch.DEFAULT_DATE_STRING;
560        } else {
561            try {
562                CmsResource res = getCms().readResource(getParamResource(), CmsResourceFilter.IGNORE_EXPIRATION);
563                if (res.getDateExpired() == CmsResource.DATE_EXPIRED_DEFAULT) {
564                    return CmsTouch.DEFAULT_DATE_STRING;
565                } else {
566                    return CmsCalendarWidget.getCalendarLocalizedTime(getLocale(), getMessages(), res.getDateExpired());
567                }
568            } catch (CmsException e) {
569                return CmsCalendarWidget.getCalendarLocalizedTime(
570                    getLocale(),
571                    getMessages(),
572                    System.currentTimeMillis());
573            }
574        }
575    }
576
577    /**
578     * Returns the current release date as String formatted in localized pattern.<p>
579     *
580     * @return the current release date as String formatted in localized pattern
581     */
582    public String getCurrentReleaseDate() {
583
584        // get the release date
585        if (isMultiOperation()) {
586            return CmsTouch.DEFAULT_DATE_STRING;
587        } else {
588            try {
589                CmsResource res = getCms().readResource(getParamResource(), CmsResourceFilter.IGNORE_EXPIRATION);
590                if (res.getDateReleased() == CmsResource.DATE_RELEASED_DEFAULT) {
591                    return CmsTouch.DEFAULT_DATE_STRING;
592                } else {
593                    return CmsCalendarWidget.getCalendarLocalizedTime(
594                        getLocale(),
595                        getMessages(),
596                        res.getDateReleased());
597                }
598            } catch (CmsException e) {
599                return CmsCalendarWidget.getCalendarLocalizedTime(
600                    getLocale(),
601                    getMessages(),
602                    System.currentTimeMillis());
603            }
604        }
605    }
606
607    /**
608     * Returns the value of the enable_notification parameter.<p>
609     *
610     * The enable_notification parameter if content notification is enabled for this resource.<p>
611     *
612     * @return the value of the enable_notification parameter
613     */
614    public String getParamEnablenotification() {
615
616        return m_paramEnablenotification;
617    }
618
619    /**
620     * Returns the value of the new expire date parameter,
621     * or null if this parameter was not provided.<p>
622     *
623     * @return the value of the new expire date parameter
624     */
625    public String getParamExpiredate() {
626
627        return m_paramExpiredate;
628    }
629
630    /**
631     * Returns the value of the leave expire parameter.<p>
632     *
633     * @return the value of the leave expire parameter
634     */
635    public String getParamLeaveexpire() {
636
637        return m_paramLeaveexpire;
638    }
639
640    /**
641     * Returns the value of the modify siblings parameter,
642     * or null if this parameter was not provided.<p>
643     *
644     * @return the value of the modify siblings
645     */
646    public String getParamModifysiblings() {
647
648        return m_paramModifysiblings;
649    }
650
651    /**
652     * Returns the value of the notification interval parameter,
653     * or null if this parameter was not provided.<p>
654     *
655     * @return the value of the notification interval parameter
656     */
657    public String getParamNotificationinterval() {
658
659        return m_paramNotificationinterval;
660    }
661
662    /**
663     * Returns the value of the recursive parameter,
664     * or null if this parameter was not provided.<p>
665     *
666     * The recursive parameter on folders decides if all subresources
667     * of the folder should be touched, too.<p>
668     *
669     * @return the value of the recursive parameter
670     */
671    public String getParamRecursive() {
672
673        return m_paramRecursive;
674    }
675
676    /**
677     * Returns the value of the new release date parameter,
678     * or null if this parameter was not provided.<p>
679     *
680     * The release date parameter stores the new release date as String.<p>
681     *
682     * @return the value of the new release date parameter
683     */
684    public String getParamReleasedate() {
685
686        return m_paramReleasedate;
687    }
688
689    /**
690     * Returns the value of the reset expire parameter.<p>
691     *
692     * @return the value of the reset expire parameter
693     */
694    public String getParamResetexpire() {
695
696        return m_paramResetexpire;
697    }
698
699    /**
700     * Returns the value of the reset release parameter.<p>
701     *
702     * @return the value of the reset release parameter
703     */
704    public String getParamResetrelease() {
705
706        return m_paramResetrelease;
707    }
708
709    /**
710     * Sets the value of the enable notification parameter.<p>
711     *
712     * @param value the value to set
713     */
714    public void setParamEnablenotification(String value) {
715
716        m_paramEnablenotification = value;
717    }
718
719    /**
720     * Sets the value of the expire date.<p>
721     *
722     * @param value the value to set
723     */
724    public void setParamExpiredate(String value) {
725
726        m_paramExpiredate = value;
727    }
728
729    /**
730     * Sets the value of the leave expire parameter.<p>
731     *
732     * @param paramLeaveexpire the value of the leave expire parameter
733     */
734    public void setParamLeaveexpire(String paramLeaveexpire) {
735
736        m_paramLeaveexpire = paramLeaveexpire;
737    }
738
739    /**
740     * Sets the value of the modify siblings parameter.<p>
741     *
742     * @param value the value to set
743     */
744    public void setParamModifysiblings(String value) {
745
746        m_paramModifysiblings = value;
747    }
748
749    /**
750     * Sets the value of the new time stamp parameter.<p>
751     *
752     * @param value the value to set
753     */
754    public void setParamNotificationinterval(String value) {
755
756        m_paramNotificationinterval = value;
757    }
758
759    /**
760     * Sets the value of the recursive parameter.<p>
761     *
762     * @param value the value to set
763     */
764    public void setParamRecursive(String value) {
765
766        m_paramRecursive = value;
767    }
768
769    /**
770     * Sets the value of the release date parameter.<p>
771     *
772     * @param value the value to set
773     */
774    public void setParamReleasedate(String value) {
775
776        m_paramReleasedate = value;
777    }
778
779    /**
780     * Sets the value of the reset expire parameter.<p>
781     *
782     * @param paramResetexpire the value of the reset expire parameter
783     */
784    public void setParamResetexpire(String paramResetexpire) {
785
786        m_paramResetexpire = paramResetexpire;
787    }
788
789    /**
790     * Sets the value of the reset release parameter.<p>
791     *
792     * @param paramResetrelease the value of the reset release parameter
793     */
794    public void setParamResetrelease(String paramResetrelease) {
795
796        m_paramResetrelease = paramResetrelease;
797    }
798
799    /**
800     * Returns a localized String for "Group", if the flag of a group ACE, and the localization for "User" otherwise.<p>
801     *
802     * @param flags the flags of the ACE
803     *
804     * @return localization for "Group", if the flag belongs to a group ACE
805     */
806    protected String getLocalizedType(int flags) {
807
808        if ((flags & CmsAccessControlEntry.ACCESS_FLAGS_USER) > 0) {
809            return key(Messages.GUI_LABEL_USER_0);
810        } else {
811            return key(Messages.GUI_LABEL_GROUP_0);
812        }
813    }
814
815    /**
816     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
817     */
818    @Override
819    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
820
821        // fill the parameter values in the get/set methods
822        fillParamValues(request);
823
824        // check the required permissions to modify the resource
825        if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) {
826            // no write permissions for the resource, set cancel action to close dialog
827            setParamAction(DIALOG_CANCEL);
828        }
829
830        // set the dialog type
831        setParamDialogtype(DIALOG_TYPE);
832
833        // set the action for the JSP switch
834        if (DIALOG_TYPE.equals(getParamAction())) {
835            setAction(ACTION_OK);
836        } else if (DIALOG_WAIT.equals(getParamAction())) {
837            setAction(ACTION_WAIT);
838        } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) {
839            setAction(ACTION_LOCKS_CONFIRMED);
840        } else if (DIALOG_CANCEL.equals(getParamAction())) {
841            setAction(ACTION_CANCEL);
842        } else {
843            setAction(ACTION_DEFAULT);
844            // build title for dialog
845            setDialogTitle(
846                Messages.GUI_AVAILABILITY_NOTIFICATION_SETTINGS_1,
847                Messages.GUI_AVAILABILITY_NOTIFICATION_MULTI_2);
848        }
849    }
850
851    /**
852     * Modifies the release and expire date of a resource, and changes the notification interval. <p>
853     *
854     * @return true, if the operation was performed, otherwise false
855     * @throws CmsException if modification is not successful
856     */
857    @Override
858    protected boolean performDialogOperation() throws CmsException {
859
860        // check if the current resource is a folder for single operation
861        boolean isFolder = isOperationOnFolder();
862        // on folder deletion or multi operation display "please wait" screen, not for simple file deletion
863        if ((isMultiOperation() || isFolder) && !DIALOG_WAIT.equals(getParamAction())) {
864            // return false, this will trigger the "please wait" screen
865            return false;
866        }
867
868        // get the new release date for the resource(s) from request parameter
869        long releaseDate = CmsResource.DATE_RELEASED_DEFAULT;
870        boolean resetReleaseDate = Boolean.valueOf(getParamResetrelease()).booleanValue();
871        boolean leaveReleaseDate = false;
872        if (!resetReleaseDate) {
873            try {
874                if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParamReleasedate()))
875                    && (!getParamReleasedate().startsWith(CmsTouch.DEFAULT_DATE_STRING))) {
876                    releaseDate = CmsCalendarWidget.getCalendarDate(getMessages(), getParamReleasedate(), true);
877                } else {
878                    leaveReleaseDate = true;
879                }
880            } catch (ParseException e) {
881                throw new CmsException(
882                    Messages.get().container(Messages.ERR_PARSE_RELEASEDATE_1, getParamReleasedate()),
883                    e);
884            }
885        }
886
887        // get the new expire date for the resource(s) from request parameter
888        long expireDate = CmsResource.DATE_EXPIRED_DEFAULT;
889        boolean resetExpireDate = Boolean.valueOf(getParamResetexpire()).booleanValue();
890        boolean leaveExpireDate = false;
891        if (!resetExpireDate) {
892            try {
893                if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParamExpiredate()))
894                    && (!getParamExpiredate().startsWith(CmsTouch.DEFAULT_DATE_STRING))) {
895                    expireDate = CmsCalendarWidget.getCalendarDate(getMessages(), getParamExpiredate(), true);
896                } else {
897                    leaveExpireDate = true;
898                }
899            } catch (ParseException e) {
900                throw new CmsException(
901                    Messages.get().container(Messages.ERR_PARSE_EXPIREDATE_1, getParamExpiredate()),
902                    e);
903            }
904        }
905
906        // get the flag if the operation is recursive from request parameter
907        boolean modifyRecursive = Boolean.valueOf(getParamRecursive()).booleanValue();
908
909        // now iterate the resource(s)
910        Iterator<String> i = getResourceList().iterator();
911        while (i.hasNext()) {
912            String resName = i.next();
913            try {
914                performSingleResourceAvailability(
915                    resName,
916                    releaseDate,
917                    expireDate,
918                    leaveReleaseDate,
919                    leaveExpireDate,
920                    modifyRecursive);
921            } catch (CmsException e) {
922                // collect exceptions to create a detailed output
923                addMultiOperationException(e);
924            }
925        }
926
927        boolean notificationEnabled = Boolean.valueOf(getParamEnablenotification()).booleanValue();
928        int notificationInterval = 0;
929        try {
930            notificationInterval = Integer.parseInt(getParamNotificationinterval());
931        } catch (Throwable e) {
932            // ignore
933        }
934
935        // get the flag if the operation should be executed on resource siblings, too
936        boolean modifySiblings = Boolean.valueOf(getParamModifysiblings()).booleanValue();
937
938        // now iterate the resource(s)
939        i = getResourceList().iterator();
940        while (i.hasNext()) {
941            String resName = i.next();
942            try {
943                performSingleResourceNotification(
944                    getCms(),
945                    resName,
946                    notificationEnabled,
947                    notificationInterval,
948                    modifySiblings);
949            } catch (CmsException e) {
950                // collect exceptions to create a detailed output
951                addMultiOperationException(e);
952            }
953        }
954        checkMultiOperationException(Messages.get(), Messages.ERR_AVAILABILITY_MULTI_0);
955
956        return true;
957    }
958
959    /**
960     * Performs the availability operations on a single resource.<p>
961     *
962     * @param resName the VFS path of the resource
963     * @param releaseDate the new release date
964     * @param expireDate the new expiration date
965     * @param leaveRelease if the release date should be left untouched
966     * @param leaveExpire if the expiration date should be left untouched
967     * @param modifyRecursive flag indicating if the operation is recursive for folders
968     *
969     * @throws CmsException if the availability and notification operations fail
970     */
971    protected void performSingleResourceAvailability(
972        String resName,
973        long releaseDate,
974        long expireDate,
975        boolean leaveRelease,
976        boolean leaveExpire,
977        boolean modifyRecursive) throws CmsException {
978
979        CmsResource resource = getCms().readResource(resName, CmsResourceFilter.IGNORE_EXPIRATION);
980        if (leaveRelease) {
981            releaseDate = resource.getDateReleased();
982        }
983        if (leaveExpire) {
984            expireDate = resource.getDateExpired();
985        }
986        if (expireDate < releaseDate) {
987            throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_AVAILABILITY_BAD_TIMEWINDOW_0));
988        }
989        String resourcePath = getCms().getSitePath(resource);
990        // lock resource if auto lock is enabled
991        checkLock(resourcePath);
992        // modify release and expire date of the resource if needed
993        if (!leaveRelease) {
994            getCms().setDateReleased(resourcePath, releaseDate, modifyRecursive);
995        }
996        if (!leaveExpire) {
997            getCms().setDateExpired(resourcePath, expireDate, modifyRecursive);
998        }
999    }
1000}