001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
005 *
006 * This library is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 2.1 of the License, or (at your option) any later version.
010 *
011 * This library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * For further information about Alkacon Software GmbH & Co. KG, please see the
017 * company website: http://www.alkacon.com
018 *
019 * For further information about OpenCms, please see the
020 * project website: http://www.opencms.org
021 *
022 * You should have received a copy of the GNU Lesser General Public
023 * License along with this library; if not, write to the Free Software
024 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
025 *
026 */
027
028package org.opencms.workplace;
029
030import org.opencms.file.CmsResource;
031import org.opencms.file.CmsResourceFilter;
032import org.opencms.i18n.CmsEncoder;
033import org.opencms.i18n.CmsMessageContainer;
034import org.opencms.jsp.CmsJspActionElement;
035import org.opencms.main.CmsException;
036import org.opencms.main.CmsLog;
037import org.opencms.main.OpenCms;
038import org.opencms.security.CmsPermissionSet;
039import org.opencms.staticexport.CmsLinkManager;
040import org.opencms.ui.CmsVaadinUtils;
041import org.opencms.ui.apps.CmsAppHierarchyConfiguration;
042import org.opencms.util.CmsRequestUtil;
043import org.opencms.util.CmsStringUtil;
044import org.opencms.workplace.editors.CmsPreEditorAction;
045import org.opencms.workplace.tools.CmsToolDialog;
046import org.opencms.workplace.tools.CmsToolManager;
047
048import java.io.IOException;
049import java.util.HashMap;
050import java.util.Map;
051
052import javax.servlet.http.HttpServletRequest;
053import javax.servlet.http.HttpServletResponse;
054import javax.servlet.jsp.JspException;
055import javax.servlet.jsp.JspWriter;
056import javax.servlet.jsp.PageContext;
057
058import org.apache.commons.logging.Log;
059
060/**
061 * Provides methods for building the dialog windows of OpenCms.<p>
062 *
063 * @since 6.0.0
064 */
065public class CmsDialog extends CmsToolDialog {
066
067    /** Value for the action: cancel. */
068    public static final int ACTION_CANCEL = 4;
069
070    /** Value for the action: close popup window. */
071    public static final int ACTION_CLOSEPOPUP = 6;
072
073    /** Value for the action: save & close popup window. */
074    public static final int ACTION_CLOSEPOPUP_SAVE = 7;
075
076    /** Value for the action: confirmed. */
077    public static final int ACTION_CONFIRMED = 1;
078
079    /** Value for the action: continue. */
080    public static final int ACTION_CONTINUE = 8;
081
082    /** Value for the action: default (show initial dialog form). */
083    public static final int ACTION_DEFAULT = 0;
084
085    /** Value for the action: locks confirmed. */
086    public static final int ACTION_LOCKS_CONFIRMED = 99;
087
088    /** Value for the action: ok. */
089    public static final int ACTION_OK = 3;
090
091    // note: action values 90 - 99 are reserved for reports
092    /** Value for the action: begin the report. */
093    public static final int ACTION_REPORT_BEGIN = 90;
094
095    /** Value for the action: end the report. */
096    public static final int ACTION_REPORT_END = 92;
097
098    /** Value for the action: update the report. */
099    public static final int ACTION_REPORT_UPDATE = 91;
100
101    /** Value for the action: button "set" clicked. */
102    public static final int ACTION_SET = 5;
103
104    /** Value for the action: wait (show please wait screen). */
105    public static final int ACTION_WAIT = 2;
106
107    /** Constant for the "Advanced" button in the build button methods. */
108    public static final int BUTTON_ADVANCED = 3;
109
110    /** Constant for the "Back" button in the build button methods. */
111    public static final int BUTTON_BACK = 9;
112
113    /** Constant for the "Cancel" button in the build button methods. */
114    public static final int BUTTON_CANCEL = 1;
115
116    /** Constant for the "Close" button in the build button methods. */
117    public static final int BUTTON_CLOSE = 2;
118
119    /** Constant for the "Continue" button in the build button methods. */
120    public static final int BUTTON_CONTINUE = 10;
121
122    /** Constant for the "Details" button in the build button methods. */
123    public static final int BUTTON_DETAILS = 5;
124
125    /** Constant for the "Discard" button in the build button methods (same function as "Cancel" button but different text on button. */
126    public static final int BUTTON_DISCARD = 8;
127
128    /** Constant for the "Edit" button in the build button methods (same function as "Ok" button but different text on button. */
129    public static final int BUTTON_EDIT = 7;
130
131    /** Constant for the "OK" button in the build button methods. */
132    public static final int BUTTON_OK = 0;
133
134    /** Constant for the "OK" button in the build button methods (without form submission). */
135    public static final int BUTTON_OK_NO_SUBMIT = 6;
136
137    /** Constant for the "Set" button in the build button methods. */
138    public static final int BUTTON_SET = 4;
139
140    /** Request parameter value for the action: back. */
141    public static final String DIALOG_BACK = "back";
142
143    /** Request parameter value for the action: cancel. */
144    public static final String DIALOG_CANCEL = "cancel";
145
146    /** Request parameter value for the action: dialog confirmed. */
147    public static final String DIALOG_CONFIRMED = "confirmed";
148
149    /** Request parameter value for the action: continue. */
150    public static final String DIALOG_CONTINUE = "continue";
151
152    /** Request parameter value for the action: initial call. */
153    public static final String DIALOG_INITIAL = "initial";
154
155    /** Request parameter value for the action: dialog locks confirmed. */
156    public static final String DIALOG_LOCKS_CONFIRMED = "locksconfirmed";
157
158    /** Request parameter value for the action: ok. */
159    public static final String DIALOG_OK = "ok";
160
161    /** Request parameter value for the action: set. */
162    public static final String DIALOG_SET = "set";
163
164    /** Request parameter value for the action: show please wait screen. */
165    public static final String DIALOG_WAIT = "wait";
166
167    /** Request parameter name for the action. */
168    public static final String PARAM_ACTION = "action";
169
170    /** Request parameter name for the action. */
171    public static final String PARAM_ACTION_VALUE_FOR_CHANGED_INDEX = "index";
172
173    /** Request parameter name for the closelink. */
174    public static final String PARAM_CLOSELINK = "closelink";
175
176    /** Request parameter name for the dialog type. */
177    public static final String PARAM_DIALOGTYPE = "dialogtype";
178
179    /** Request parameter name for the error stack. */
180    public static final String PARAM_ERRORSTACK = "errorstack";
181
182    /** Request parameter name for the file. */
183    public static final String PARAM_FILE = "file";
184
185    /** Request parameter name for the frame name. */
186    public static final String PARAM_FRAMENAME = "framename";
187
188    /** Request parameter name for the "is popup" flag. */
189    public static final String PARAM_ISPOPUP = "ispopup";
190
191    /** Request parameter name for the lock. */
192    public static final String PARAM_LOCK = "lock";
193
194    /** Request parameter name for the error message. */
195    public static final String PARAM_MESSAGE = "message";
196
197    /** Request parameter name for the originalparams. */
198    public static final String PARAM_ORIGINALPARAMS = "originalparams";
199
200    /** Request parameter name for the preactiondone. */
201    public static final String PARAM_PREACTIONDONE = "preactiondone";
202
203    /** Request parameter name for the redirect flag. */
204    public static final String PARAM_REDIRECT = "redirect";
205
206    /** Request parameter name for the resource. */
207    public static final String PARAM_RESOURCE = "resource";
208
209    /** Request parameter name for the target. */
210    public static final String PARAM_TARGET = "target";
211
212    /** Request parameter name for the thread id. */
213    public static final String PARAM_THREAD = "thread";
214
215    /** Request parameter name for indicating if another thread is following the current one. */
216    public static final String PARAM_THREAD_HASNEXT = "threadhasnext";
217
218    /** Request parameter name for the dialog title. */
219    public static final String PARAM_TITLE = "title";
220
221    /** Request parameter value for the action: begin the report. */
222    public static final String REPORT_BEGIN = "reportbegin";
223
224    /** Request parameter value for the action: end the report. */
225    public static final String REPORT_END = "reportend";
226
227    /** Request parameter value for the action: update the report. */
228    public static final String REPORT_UPDATE = "reportupdate";
229
230    /** Key name for the throwable attribute. */
231    protected static final String ATTRIBUTE_THROWABLE = "throwable";
232
233    /** The log object for this class. */
234    private static final Log LOG = CmsLog.getLog(CmsDialog.class);
235
236    /** The dialog action. */
237    private int m_action;
238
239    /**
240     * The custom mapping for online help.<p>
241     *
242     * It will be translated to a javascript variable called onlineHelpUriCustom.
243     * If it is set, the top.head javascript for the online help will use this value. <p>
244     */
245    private String m_onlineHelpUriCustom;
246
247    /** The dialog action parameter. */
248    private String m_paramAction;
249
250    /** The close link parameter. */
251    private String m_paramCloseLink;
252
253    /** The dialog type. */
254    private String m_paramDialogtype;
255
256    /** The frame name parameter. */
257    private String m_paramFrameName;
258
259    /** The is popup parameter. */
260    private String m_paramIsPopup;
261
262    /** The messages parameter. */
263    private String m_paramMessage;
264
265    /** The original parameters. */
266    private String m_paramOriginalParams;
267
268    /** The pre action done parameter. */
269    private String m_paramPreActionDone;
270
271    /** The redirect parameter. */
272    private String m_paramRedirect;
273
274    /** The resource parameter. */
275    private String m_paramResource;
276
277    /** The title parameter. */
278    private String m_paramTitle;
279
280    /**
281     * Public constructor with JSP action element.<p>
282     *
283     * @param jsp an initialized JSP action element
284     */
285    public CmsDialog(CmsJspActionElement jsp) {
286
287        super(jsp);
288    }
289
290    /**
291     * Public constructor with JSP variables.<p>
292     *
293     * @param context the JSP page context
294     * @param req the JSP request
295     * @param res the JSP response
296     */
297    public CmsDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) {
298
299        this(new CmsJspActionElement(context, req, res));
300    }
301
302    /**
303     * Returns an initialized CmsDialog instance that is read from the request attributes.<p>
304     *
305     * This method is used by dialog elements.
306     * The dialog elements do not initialize their own workplace class,
307     * but use the initialized instance of the "master" class.
308     * This is required to ensure that parameters of the "master" class
309     * can properly be kept on the dialog elements.<p>
310     *
311     * To prevent null pointer exceptions, an empty dialog is returned if
312     * nothing is found in the request attributes.<p>
313     *
314     * @param context the JSP page context
315     * @param req the JSP request
316     * @param res the JSP response
317     *
318     * @return an initialized CmsDialog instance that is read from the request attributes
319     */
320    public static CmsDialog initCmsDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) {
321
322        CmsDialog wp = (CmsDialog)req.getAttribute(CmsWorkplace.SESSION_WORKPLACE_CLASS);
323        if (wp == null) {
324            // ensure that we don't get null pointers if the page is directly called
325            wp = new CmsDialog(new CmsJspActionElement(context, req, res));
326            wp.fillParamValues(req);
327        }
328        return wp;
329    }
330
331    /**
332     * Used to close the current JSP dialog.<p>
333     *
334     * This method tries to include the URI stored in the workplace settings.
335     * This URI is determined by the frame name, which has to be set
336     * in the frame name parameter.<p>
337     *
338     * @throws JspException if including an element fails
339     */
340    public void actionCloseDialog() throws JspException {
341
342        // create a map with empty "resource" parameter to avoid changing the folder when returning to explorer file list
343        Map<String, String> params = new HashMap<String, String>();
344        params.put(PARAM_RESOURCE, "");
345        if (isPopup()) {
346            JspWriter out = getJsp().getJspContext().getOut();
347            try {
348                // try to close the popup
349
350                out.write("<html><head></head>\n");
351                out.write("<body onload=\"top.close();\">\n");
352                out.write("</body>\n");
353                out.write("</html>\n");
354            } catch (IOException e) {
355                // error redirecting, include explorer file list
356                getJsp().include(FILE_EXPLORER_FILELIST, null, params);
357            } finally {
358                try {
359                    out.close();
360                } catch (IOException e) {
361                    throw new JspException(e.getMessage(), e);
362                }
363            }
364        } else if (getParamCloseLink() != null) {
365            // close link parameter present
366            try {
367                if (CmsLinkManager.isWorkplaceLink(getParamCloseLink())) {
368                    // in case the close link points to the new workplace, make sure to set the new location on the top frame
369                    openWorkplaceLink(getParamCloseLink());
370                } else if (Boolean.valueOf(getParamRedirect()).booleanValue()) {
371                    // redirect parameter is true, redirect to given close link
372                    getJsp().getResponse().sendRedirect(getParamCloseLink());
373                } else {
374                    // forward JSP
375                    if (!isForwarded()) {
376                        setForwarded(true);
377                        CmsRequestUtil.forwardRequest(
378                            getParamCloseLink(),
379                            getJsp().getRequest(),
380                            getJsp().getResponse());
381                    }
382                }
383            } catch (Exception e) {
384                // forward failed
385                throw new JspException(e.getMessage(), e);
386            }
387        } else if (getParamFramename() != null) {
388            // no workplace frame mode (currently used for galleries)
389            // frame name parameter found, get URI
390            String frameUri = getSettings().getFrameUris().get(getParamFramename());
391            // resetting the action parameter
392            params.put(PARAM_ACTION, "");
393            if (frameUri != null) {
394                // URI found, include it
395                // remove context path from URI before inclusion
396                frameUri = CmsLinkManager.removeOpenCmsContext(frameUri);
397                // include the found frame URI
398                getJsp().include(frameUri, null, params);
399            } else {
400                // no URI found, include the explorer file list
401                openLaunchpad();
402            }
403        } else {
404            // no frame name parameter found, include the explorer file list
405            openLaunchpad();
406        }
407    }
408
409    /**
410     * Returns the html code to build the ajax report container.<p>
411     *
412     * @param title the title of the report box
413     *
414     * @return html code
415     */
416    public String buildAjaxResultContainer(String title) {
417
418        StringBuffer html = new StringBuffer(512);
419        html.append(dialogBlockStart(title));
420        html.append(dialogWhiteBoxStart());
421        html.append("<div id='ajaxreport' >");
422        html.append(buildAjaxWaitMessage());
423        html.append("</div>\n");
424        html.append(dialogWhiteBoxEnd());
425        html.append(dialogBlockEnd());
426        html.append("&nbsp;<br>\n");
427        return html.toString();
428    }
429
430    /**
431     * Override to display additional options in the lock dialog.<p>
432     *
433     * @return html code to display additional options
434     */
435    public String buildLockAdditionalOptions() {
436
437        return "";
438    }
439
440    /**
441     * Returns the html code to build the confirmation messages.<p>
442     *
443     * @return html code
444     */
445    public String buildLockConfirmationMessageJS() {
446
447        StringBuffer html = new StringBuffer(512);
448        html.append("<script ><!--\n");
449        html.append("function setConfirmationMessage(locks, blockinglocks) {\n");
450        html.append("\tvar confMsg = document.getElementById('conf-msg');\n");
451        html.append("\tif (locks > -1) {\n");
452        html.append("\t\tif (blockinglocks > '0') {\n");
453        html.append("\t\t\tshowAjaxReportContent();\n");
454        html.append("\t\t\tdocument.getElementById('lock-body-id').className = '';\n");
455        html.append("\t\t\tdocument.getElementById('butClose').className = '';\n");
456        html.append("\t\t\tdocument.getElementById('butContinue').className = 'hide';\n");
457        html.append("\t\t\tconfMsg.innerHTML = '");
458        html.append(key(org.opencms.workplace.commons.Messages.GUI_OPERATION_BLOCKING_LOCKS_0));
459        html.append("';\n");
460        html.append("\t\t} else {\n");
461        html.append("\t\t\tsubmitAction('");
462        html.append(CmsDialog.DIALOG_OK);
463        html.append("', null, 'main');\n");
464        html.append("\t\t\tdocument.forms['main'].submit();\n");
465        html.append("\t\t}\n");
466        html.append("\t} else {\n");
467        html.append("\t\tdocument.getElementById('butClose').className = '';\n");
468        html.append("\t\tdocument.getElementById('butContinue').className = 'hide';\n");
469        html.append("\t\tconfMsg.innerHTML = '");
470        html.append(key(Messages.GUI_AJAX_REPORT_WAIT_0));
471        html.append("';\n");
472        html.append("\t}\n");
473        html.append("}\n");
474        html.append("// -->\n");
475        html.append("</script>\n");
476        return html.toString();
477    }
478
479    /**
480     * Returns the html code to build the header box.<p>
481     *
482     * @return html code
483     *
484     * @throws CmsException if something goes wrong
485     */
486    public String buildLockHeaderBox() throws CmsException {
487
488        StringBuffer html = new StringBuffer(512);
489        // include resource info
490        html.append(dialogBlockStart(null));
491        html.append(key(org.opencms.workplace.commons.Messages.GUI_LABEL_TITLE_0));
492        html.append(": ");
493        html.append(getJsp().property("Title", getParamResource(), ""));
494        html.append("<br>\n");
495        html.append(key(org.opencms.workplace.commons.Messages.GUI_LABEL_STATE_0));
496        html.append(": ");
497        html.append(getState());
498        html.append("<br>\n");
499        html.append(key(org.opencms.workplace.commons.Messages.GUI_LABEL_PERMALINK_0));
500        html.append(": ");
501        html.append(OpenCms.getLinkManager().getPermalink(getCms(), getParamResource()));
502        html.append(dialogBlockEnd());
503        return html.toString();
504    }
505
506    /**
507     * Builds the outer dialog window border.<p>
508     *
509     * @param segment the HTML segment (START / END)
510     * @param attributes optional additional attributes for the opening dialog table
511     *
512     * @return a dialog window start / end segment
513     */
514    public String dialog(int segment, String attributes) {
515
516        if (segment == HTML_START) {
517            StringBuffer html = new StringBuffer(512);
518            if (useNewStyle()) {
519                html.append(dialogTitle());
520            }
521            html.append("<table class=\"dialog\" cellpadding=\"0\" cellspacing=\"0\"");
522            if (attributes != null) {
523                html.append(" ");
524                html.append(attributes);
525            }
526            html.append("><tr><td>\n<table class=\"dialogbox\" cellpadding=\"0\" cellspacing=\"0\">\n");
527            html.append("<tr><td>\n");
528            if (useNewStyle() && getToolManager().hasToolPathForUrl(getJsp().getRequestContext().getUri())) {
529                html.append(getAdminTool().groupHtml(this));
530            }
531            return html.toString();
532        } else {
533            return "</td></tr></table>\n</td></tr></table>\n<p>&nbsp;</p>\n";
534        }
535    }
536
537    /**
538     * Builds a block with 3D border and optional subheadline in the dialog content area.<p>
539     *
540     * @param segment the HTML segment (START / END)
541     * @param headline the headline String for the block
542     * @param error if true, an error block will be created
543     *
544     * @return 3D block start / end segment
545     */
546    public String dialogBlock(int segment, String headline, boolean error) {
547
548        if (segment == HTML_START) {
549            StringBuffer result = new StringBuffer(512);
550            String errorStyle = "";
551            if (error) {
552                errorStyle = " dialogerror";
553            }
554            result.append("<!-- 3D block start -->\n");
555            result.append("<fieldset class=\"dialogblock\">\n");
556            if (CmsStringUtil.isNotEmpty(headline)) {
557                result.append("<legend>");
558                result.append("<span class=\"textbold");
559                result.append(errorStyle);
560                result.append("\" unselectable=\"on\">");
561                result.append(headline);
562                result.append("</span></legend>\n");
563            }
564            return result.toString();
565        } else {
566            return "</fieldset>\n<!-- 3D block end -->\n";
567        }
568    }
569
570    /**
571     * Builds the end HTML for a block with 3D border in the dialog content area.<p>
572     *
573     * @return 3D block start / end segment
574     */
575    public String dialogBlockEnd() {
576
577        return dialogBlock(HTML_END, null, false);
578    }
579
580    /**
581     * Builds the start HTML for a block with 3D border and optional subheadline in the dialog content area.<p>
582     *
583     * @param headline the headline String for the block
584     *
585     * @return 3D block start / end segment
586     */
587    public String dialogBlockStart(String headline) {
588
589        return dialogBlock(HTML_START, headline, false);
590    }
591
592    /**
593     * Builds the button row under the dialog content area without the buttons.<p>
594     *
595     * @param segment the HTML segment (START / END)
596     *
597     * @return the button row start / end segment
598     */
599    public String dialogButtonRow(int segment) {
600
601        if (segment == HTML_START) {
602            return "<!-- button row start -->\n<div class=\"dialogbuttons\" unselectable=\"on\">\n";
603        } else {
604            return "</div>\n<!-- button row end -->\n";
605        }
606    }
607
608    /**
609     * Builds the end of the button row under the dialog content area without the buttons.<p>
610     *
611     * @return the button row end segment
612     */
613    public String dialogButtonRowEnd() {
614
615        return dialogButtonRow(HTML_END);
616    }
617
618    /**
619     * Builds the start of the button row under the dialog content area without the buttons.<p>
620     *
621     * @return the button row start segment
622     */
623    public String dialogButtonRowStart() {
624
625        return dialogButtonRow(HTML_START);
626    }
627
628    /**
629     * Builds the html for the button row under the dialog content area, including buttons.<p>
630     *
631     * @param buttons array of constants of which buttons to include in the row
632     * @param attributes array of Strings for additional button attributes
633     *
634     * @return the html for the button row under the dialog content area, including buttons
635     */
636    public String dialogButtons(int[] buttons, String[] attributes) {
637
638        StringBuffer result = new StringBuffer(256);
639        result.append(dialogButtonRow(HTML_START));
640        for (int i = 0; i < buttons.length; i++) {
641            dialogButtonsHtml(result, buttons[i], attributes[i]);
642        }
643        result.append(dialogButtonRow(HTML_END));
644        return result.toString();
645    }
646
647    /**
648     * Builds a button row with a single "close" button.<p>
649     *
650     * @return the button row
651     */
652    public String dialogButtonsClose() {
653
654        return dialogButtons(new int[] {BUTTON_CLOSE}, new String[1]);
655    }
656
657    /**
658     * Builds a button row with a single "close" button.<p>
659     *
660     * @param closeAttribute additional attributes for the "close" button
661     *
662     * @return the button row
663     */
664    public String dialogButtonsClose(String closeAttribute) {
665
666        return dialogButtons(new int[] {BUTTON_CLOSE}, new String[] {closeAttribute});
667    }
668
669    /**
670     * Builds a button row with a "close" and a "details" button.<p>
671     *
672     * @param closeAttribute additional attributes for the "close" button
673     * @param detailsAttribute additional attributes for the "details" button
674     *
675     * @return the button row
676     */
677    public String dialogButtonsCloseDetails(String closeAttribute, String detailsAttribute) {
678
679        return dialogButtons(new int[] {BUTTON_CLOSE, BUTTON_DETAILS}, new String[] {closeAttribute, detailsAttribute});
680    }
681
682    /**
683     * Builds a button row with a single "ok" button.<p>
684     *
685     * @return the button row
686     */
687    public String dialogButtonsOk() {
688
689        return dialogButtons(new int[] {BUTTON_OK}, new String[1]);
690    }
691
692    /**
693     * Builds a button row with a single "ok" button.<p>
694     *
695     * @param okAttribute additional attributes for the "ok" button
696     *
697     * @return the button row
698     */
699    public String dialogButtonsOk(String okAttribute) {
700
701        return dialogButtons(new int[] {BUTTON_OK}, new String[] {okAttribute});
702    }
703
704    /**
705     * Builds a button row with an "ok" and a "cancel" button.<p>
706     *
707     * @return the button row
708     */
709    public String dialogButtonsOkCancel() {
710
711        return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[2]);
712    }
713
714    /**
715     * Builds a button row with an "ok" and a "cancel" button.<p>
716     *
717     * @param okAttributes additional attributes for the "ok" button
718     * @param cancelAttributes additional attributes for the "cancel" button
719     *
720     * @return the button row
721     */
722    public String dialogButtonsOkCancel(String okAttributes, String cancelAttributes) {
723
724        return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[] {okAttributes, cancelAttributes});
725    }
726
727    /**
728     * Builds a button row with an "ok", a "cancel" and an "advanced" button.<p>
729     *
730     * @param okAttributes additional attributes for the "ok" button
731     * @param cancelAttributes additional attributes for the "cancel" button
732     * @param advancedAttributes additional attributes for the "advanced" button
733     *
734     * @return the button row
735     */
736    public String dialogButtonsOkCancelAdvanced(
737        String okAttributes,
738        String cancelAttributes,
739        String advancedAttributes) {
740
741        return dialogButtons(
742            new int[] {BUTTON_OK, BUTTON_CANCEL, BUTTON_ADVANCED},
743            new String[] {okAttributes, cancelAttributes, advancedAttributes});
744    }
745
746    /**
747     * Builds a button row with a "set", an "ok", and a "cancel" button.<p>
748     *
749     * @param setAttributes additional attributes for the "set" button
750     * @param okAttributes additional attributes for the "ok" button
751     * @param cancelAttributes additional attributes for the "cancel" button
752     *
753     * @return the button row
754     */
755    public String dialogButtonsSetOkCancel(String setAttributes, String okAttributes, String cancelAttributes) {
756
757        return dialogButtons(
758            new int[] {BUTTON_SET, BUTTON_OK, BUTTON_CANCEL},
759            new String[] {setAttributes, okAttributes, cancelAttributes});
760    }
761
762    /**
763     * Builds the content area of the dialog window.<p>
764     *
765     * @param segment the HTML segment (START / END)
766     * @param title the title String for the dialog window
767     *
768     * @return a content area start / end segment
769     */
770    public String dialogContent(int segment, String title) {
771
772        if (segment == HTML_START) {
773            StringBuffer result = new StringBuffer(512);
774            // null title is ok, we always want the title headline
775            result.append(dialogHead(title));
776            result.append("<div class=\"dialogcontent\" unselectable=\"on\">\n");
777            result.append("<!-- dialogcontent start -->\n");
778            return result.toString();
779        } else {
780            return "<!-- dialogcontent end -->\n</div>\n";
781        }
782    }
783
784    /**
785     * Returns the end html for the content area of the dialog window.<p>
786     *
787     * @return the end html for the content area of the dialog window
788     */
789    public String dialogContentEnd() {
790
791        return dialogContent(HTML_END, null);
792    }
793
794    /**
795     * Returns the start html for the content area of the dialog window.<p>
796     *
797     * @param title the title for the dialog
798     *
799     * @return the start html for the content area of the dialog window
800     */
801    public String dialogContentStart(String title) {
802
803        return dialogContent(HTML_START, title);
804    }
805
806    /**
807     * Returns the end html for the outer dialog window border.<p>
808     *
809     * @return the end html for the outer dialog window border
810     */
811    public String dialogEnd() {
812
813        return dialog(HTML_END, null);
814    }
815
816    /**
817     * Builds the title of the dialog window.<p>
818     *
819     * @param title the title String for the dialog window
820     *
821     * @return the HTML title String for the dialog window
822     */
823    public String dialogHead(String title) {
824
825        String escapedTitle;
826        if (title == null) {
827            escapedTitle = "";
828        } else {
829            escapedTitle = CmsEncoder.escapeHtml(title);
830        }
831
832        return "<div class=\"dialoghead\" unselectable=\"on\">" + escapedTitle + "</div>";
833    }
834
835    /**
836     * Builds an invisible horizontal spacer with the specified width.<p>
837     *
838     * @param width the width of the spacer in pixels
839     *
840     * @return an invisible horizontal spacer with the specified width
841     */
842    public String dialogHorizontalSpacer(int width) {
843
844        return "<td><span style=\"display:block; height: 1px; width: " + width + "px;\"></span></td>";
845    }
846
847    /**
848     * Builds the necessary button row.<p>
849     *
850     * @return the button row
851     */
852    public String dialogLockButtons() {
853
854        StringBuffer html = new StringBuffer(512);
855        html.append("<div id='butClose' >\n");
856        html.append(dialogButtonsClose());
857        html.append("</div>\n");
858        html.append("<div id='butContinue' class='hide' >\n");
859        html.append(
860            dialogButtons(
861                new int[] {BUTTON_CONTINUE, BUTTON_CANCEL},
862                new String[] {" onclick=\"submitAction('" + DIALOG_OK + "', form); form.submit();\"", ""}));
863        html.append("</div>\n");
864        return html.toString();
865    }
866
867    /**
868     * Builds a dialog line without break (display: block).<p>
869     *
870     * @param segment the HTML segment (START / END)
871     *
872     * @return a row start / end segment
873     */
874    public String dialogRow(int segment) {
875
876        if (segment == HTML_START) {
877            return "<div class=\"dialogrow\">";
878        } else {
879            return "</div>\n";
880        }
881    }
882
883    /**
884     * Builds the end of a dialog line without break (display: block).<p>
885     *
886     * @return the row end segment
887     */
888    public String dialogRowEnd() {
889
890        return dialogRow(HTML_END);
891    }
892
893    /**
894     * Builds the start of a dialog line without break (display: block).<p>
895     *
896     * @return the row start segment
897     */
898    public String dialogRowStart() {
899
900        return dialogRow(HTML_START);
901    }
902
903    /**
904     * Builds the standard javascript for submitting the dialog.<p>
905     *
906     * @return the standard javascript for submitting the dialog
907     */
908    @Override
909    public String dialogScriptSubmit() {
910
911        if (useNewStyle()) {
912            return super.dialogScriptSubmit();
913        }
914        StringBuffer result = new StringBuffer(512);
915        result.append("function submitAction(actionValue, theForm, formName) {\n");
916        result.append("\tif (theForm == null) {\n");
917        result.append("\t\ttheForm = document.forms[formName];\n");
918        result.append("\t}\n");
919        result.append("\ttheForm." + PARAM_FRAMENAME + ".value = window.name;\n");
920        result.append("\tif (actionValue == \"" + DIALOG_OK + "\") {\n");
921        result.append("\t\treturn true;\n");
922        result.append("\t}\n");
923        result.append("\ttheForm." + PARAM_ACTION + ".value = actionValue;\n");
924        result.append("\ttheForm.submit();\n");
925        result.append("\treturn false;\n");
926        result.append("}\n");
927
928        return result.toString();
929    }
930
931    /**
932     * Builds a horizontal separator line in the dialog content area.<p>
933     *
934     * @return a separator element
935     */
936    public String dialogSeparator() {
937
938        return "<div class=\"dialogseparator\" unselectable=\"on\"></div>";
939    }
940
941    /**
942     * Builds a space between two elements in the dialog content area.<p>
943     *
944     * @return a space element
945     */
946    public String dialogSpacer() {
947
948        return "<div class=\"dialogspacer\" unselectable=\"on\">&nbsp;</div>";
949    }
950
951    /**
952     * Returns the start html for the outer dialog window border.<p>
953     *
954     * @return the start html for the outer dialog window border
955     */
956    public String dialogStart() {
957
958        return dialog(HTML_START, null);
959    }
960
961    /**
962     * Returns the start html for the outer dialog window border.<p>
963     *
964     * @param attributes optional html attributes to insert
965     *
966     * @return the start html for the outer dialog window border
967     */
968    public String dialogStart(String attributes) {
969
970        return dialog(HTML_START, attributes);
971    }
972
973    /**
974     * Builds a subheadline in the dialog content area.<p>
975     *
976     * @param headline the desired headline string
977     *
978     * @return a subheadline element
979     */
980    public String dialogSubheadline(String headline) {
981
982        StringBuffer retValue = new StringBuffer(128);
983        retValue.append("<div class=\"dialogsubheader\" unselectable=\"on\">");
984        retValue.append(headline);
985        retValue.append("</div>\n");
986        return retValue.toString();
987    }
988
989    /**
990     * Builds the HTML code to fold and unfold a white-box.<p>
991     *
992     * @param headline the heading to display
993     * @param id the id of the toggle
994     * @param show true if the white box is open at the beginning
995     *
996     * @return HTML code to fold and unfold a white-box
997     */
998    public String dialogToggleStart(String headline, String id, boolean show) {
999
1000        StringBuffer result = new StringBuffer(512);
1001        // set icon and style class to use: hide user permissions
1002        String image = "plus.png";
1003        String styleClass = "hide";
1004        if (show) {
1005            // show user permissions
1006            image = "minus.png";
1007            styleClass = "show";
1008        }
1009
1010        result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n");
1011        result.append("<tr>\n");
1012        result.append(
1013            "\t<td style=\"vertical-align: bottom; padding-bottom: 2px;\"><a href=\"javascript:toggleDetail('");
1014        result.append(id);
1015        result.append("');\"><img src=\"");
1016        result.append(getSkinUri());
1017        result.append("commons/");
1018        result.append(image);
1019        result.append("\" class=\"noborder\" id=\"ic-");
1020        result.append(id);
1021        result.append("\"></a></td>\n");
1022        result.append("\t<td>");
1023        result.append(dialogSubheadline(headline));
1024        result.append("</td>\n");
1025        result.append("</tr>\n");
1026        result.append("</table>\n");
1027
1028        result.append("<div class=\"");
1029        result.append(styleClass);
1030        result.append("\" id=\"");
1031        result.append(id);
1032        result.append("\">\n");
1033        return result.toString();
1034    }
1035
1036    /**
1037     * Builds a white box in the dialog content area.<p>
1038     *
1039     * @param segment the HTML segment (START / END)
1040     *
1041     * @return the white box start / end segment
1042     */
1043    public String dialogWhiteBox(int segment) {
1044
1045        if (segment == HTML_START) {
1046            return "<!-- white box start -->\n"
1047                + "<div class=\"dialoginnerboxborder\">\n"
1048                + "<div class=\"dialoginnerbox\" unselectable=\"off\">\n";
1049        } else {
1050            return "</div>\n</div>\n<!-- white box end -->\n";
1051        }
1052    }
1053
1054    /**
1055     * Builds the end of a white box in the dialog content area.<p>
1056     *
1057     * @return the white box end segment
1058     */
1059    public String dialogWhiteBoxEnd() {
1060
1061        return dialogWhiteBox(HTML_END);
1062    }
1063
1064    /**
1065     * Builds the start of a white box in the dialog content area.<p>
1066     *
1067     * @return the white box start segment
1068     */
1069    public String dialogWhiteBoxStart() {
1070
1071        return dialogWhiteBox(HTML_START);
1072    }
1073
1074    /**
1075     * Returns the action value.<p>
1076     *
1077     * The action value is used on JSP pages to select the proper action
1078     * in a large "switch" statement.<p>
1079     *
1080     * @return the action value
1081     */
1082    public int getAction() {
1083
1084        return m_action;
1085    }
1086
1087    /**
1088     * Returns the action to be carried out after a click on the cancel button..<p>
1089     *
1090     * @return the action to be carried out after a click on the cancel button.
1091     */
1092    public String getCancelAction() {
1093
1094        return DIALOG_CANCEL;
1095    }
1096
1097    /**
1098     * Returns the http URI of the current dialog, to be used
1099     * as value for the "action" attribute of a html form.<p>
1100     *
1101     * This URI is the real one.<p>
1102     *
1103     * @return the http URI of the current dialog
1104     */
1105    public String getDialogRealUri() {
1106
1107        return getJsp().link(getJsp().getRequestContext().getUri());
1108    }
1109
1110    /**
1111     * Returns the http URI of the current dialog, to be used
1112     * as value for the "action" attribute of a html form.<p>
1113     *
1114     * This URI could not be really the real one... <p>
1115     *
1116     * @return the http URI of the current dialog
1117     */
1118    public String getDialogUri() {
1119
1120        if (!useNewStyle()) {
1121            return getDialogRealUri();
1122        } else {
1123            return CmsToolManager.linkForToolPath(getJsp(), getCurrentToolPath());
1124        }
1125    }
1126
1127    /**
1128     * Returns the custom mapping for the online help.<p>
1129     *
1130     * @return the custom mapping for the online help
1131     */
1132    public String getOnlineHelpUriCustom() {
1133
1134        if (m_onlineHelpUriCustom == null) {
1135            return null;
1136        }
1137        StringBuffer result = new StringBuffer(m_onlineHelpUriCustom.length() + 4);
1138        result.append("\"");
1139        result.append(m_onlineHelpUriCustom);
1140        result.append("\"");
1141        return result.toString();
1142    }
1143
1144    /**
1145     * Returns the value of the action parameter,
1146     * or null if this parameter was not provided.<p>
1147     *
1148     * The action parameter is very important,
1149     * it will select the dialog action to perform.
1150     * The value of the {@link #getAction()} method will be
1151     * initialized from the action parameter.<p>
1152     *
1153     * @return the value of the action parameter
1154     */
1155    public String getParamAction() {
1156
1157        return m_paramAction;
1158    }
1159
1160    /**
1161     * Returns the value of the close link parameter,
1162     * or null if this parameter was not provided.<p>
1163     *
1164     * @return the value of the close link parameter
1165     */
1166    public String getParamCloseLink() {
1167
1168        if ((m_paramCloseLink == null) || "null".equals(m_paramCloseLink)) {
1169            return null;
1170        }
1171        return m_paramCloseLink;
1172    }
1173
1174    /**
1175     * Returns the value of the dialog type parameter,
1176     * or null if this parameter was not provided.<p>
1177     *
1178     * This parameter is very important.
1179     * It must match to the localization keys,
1180     * e.g. "copy" for the copy dialog.<p>
1181     *
1182     * This parameter must be set manually by the subclass during
1183     * first initialization.<p>
1184     *
1185     * @return the value of the dialog type parameter
1186     */
1187    public String getParamDialogtype() {
1188
1189        return m_paramDialogtype;
1190    }
1191
1192    /**
1193     * Returns the value of the frame name parameter.<p>
1194     *
1195     * @return the value of the frame name parameter
1196     */
1197    public String getParamFramename() {
1198
1199        if ((m_paramFrameName != null) && !"null".equals(m_paramFrameName)) {
1200            return m_paramFrameName;
1201        } else {
1202            return null;
1203        }
1204    }
1205
1206    /**
1207     * Returns the is popup parameter.<p>
1208     *
1209     * Use this parameter to indicate that the dialog is shown in a popup window.<p>
1210     *
1211     * @return the is popup parameter
1212     */
1213    public String getParamIsPopup() {
1214
1215        return m_paramIsPopup;
1216    }
1217
1218    /**
1219     * Returns the value of the message parameter,
1220     * or null if this parameter was not provided.<p>
1221     *
1222     * The message parameter is used on dialogs to
1223     * show any text message.<p>
1224     *
1225     * @return the value of the message parameter
1226     */
1227    public String getParamMessage() {
1228
1229        return m_paramMessage;
1230    }
1231
1232    /**
1233     * Returns the value of the original parameters parameter.<p>
1234     *
1235     * This stores the request parameter values from a previous dialog, if necessary.<p>
1236     *
1237     * @return the value of the original parameters parameter
1238     */
1239    public String getParamOriginalParams() {
1240
1241        return m_paramOriginalParams;
1242    }
1243
1244    /**
1245     * Returns the value of the preaction done parameter.<p>
1246     *
1247     * @return the value of the preaction done parameter
1248     */
1249    public String getParamPreActionDone() {
1250
1251        return m_paramPreActionDone;
1252    }
1253
1254    /**
1255     * Returns the value of the redirect flag parameter.<p>
1256     *
1257     * @return the value of the redirect flag parameter
1258     */
1259    public String getParamRedirect() {
1260
1261        return m_paramRedirect;
1262    }
1263
1264    /**
1265     * Returns the value of the file parameter,
1266     * or null if this parameter was not provided.<p>
1267     *
1268     * The file parameter selects the file on which the dialog action
1269     * is to be performed.<p>
1270     *
1271     * @return the value of the file parameter
1272     */
1273    public String getParamResource() {
1274
1275        if ((m_paramResource != null) && !"null".equals(m_paramResource)) {
1276            return m_paramResource;
1277        } else {
1278            return null;
1279        }
1280    }
1281
1282    /**
1283     * Returns the value of the title parameter,
1284     * or null if this parameter was not provided.<p>
1285     *
1286     * This parameter is used to build the title
1287     * of the dialog. It is a parameter so that the title
1288     * can be passed to included elements.<p>
1289     *
1290     * @return the value of the title parameter
1291     */
1292    public String getParamTitle() {
1293
1294        return m_paramTitle;
1295    }
1296
1297    /**
1298     * Gets a formatted file state string.<p>
1299     *
1300     * @return formatted state string
1301     *
1302     * @throws CmsException if something goes wrong
1303     */
1304    public String getState() throws CmsException {
1305
1306        if (CmsStringUtil.isNotEmpty(getParamResource())) {
1307            CmsResource file = getCms().readResource(getParamResource(), CmsResourceFilter.ALL);
1308            if (getCms().isInsideCurrentProject(getParamResource())) {
1309                return key(Messages.getStateKey(file.getState()));
1310            } else {
1311                return key(Messages.GUI_EXPLORER_STATENIP_0);
1312            }
1313        }
1314        return "+++ resource parameter not found +++";
1315    }
1316
1317    /**
1318     * Checks if the current resource has lock state exclusive or inherited.<p>
1319     *
1320     * This is used to determine whether the dialog shows the option to delete all
1321     * siblings of the resource or not.
1322     *
1323     * @return true if lock state is exclusive or inherited, otherwise false
1324     */
1325    public boolean hasCorrectLockstate() {
1326
1327        org.opencms.lock.CmsLock lock = null;
1328        try {
1329            // get the lock state for the current resource
1330            lock = getCms().getLock(getParamResource());
1331        } catch (CmsException e) {
1332            // error getting lock state, log the error and return false
1333            LOG.error(e.getLocalizedMessage(getLocale()), e);
1334            return false;
1335        }
1336        // check if auto lock feature is enabled
1337        boolean autoLockFeature = lock.isNullLock() && OpenCms.getWorkplaceManager().autoLockResources();
1338        return autoLockFeature || lock.isExclusive() || lock.isInherited();
1339    }
1340
1341    /**
1342     * Checks if this resource has siblings.<p>
1343     *
1344     * @return true if this resource has siblings
1345     */
1346    public boolean hasSiblings() {
1347
1348        try {
1349            return getCms().readResource(getParamResource(), CmsResourceFilter.ALL).getSiblingCount() > 1;
1350        } catch (CmsException e) {
1351            LOG.error(e.getLocalizedMessage(getLocale()), e);
1352            return false;
1353        }
1354
1355    }
1356
1357    /**
1358     * Builds the start html of the page, including setting of DOCTYPE and
1359     * inserting a header with the content-type.<p>
1360     *
1361     * @return the start html of the page
1362     */
1363    public String htmlStart() {
1364
1365        return pageHtml(HTML_START, null);
1366    }
1367
1368    /**
1369     * Builds the start html of the page, including setting of DOCTYPE and
1370     * inserting a header with the content-type.<p>
1371     *
1372     * This overloads the default method of the parent class.<p>
1373     *
1374     * @param helpUrl the key for the online help to include on the page
1375     *
1376     * @return the start html of the page
1377     */
1378    @Override
1379    public String htmlStart(String helpUrl) {
1380
1381        return pageHtml(HTML_START, helpUrl);
1382    }
1383
1384    /**
1385     * Builds the start html of the page, including setting of DOCTYPE and
1386     * inserting a header with the content-type.<p>
1387     *
1388     * @param helpUrl the key for the online help to include on the page
1389     * @param title the title for the page
1390     *
1391     * @return the start html of the page
1392     */
1393    public String htmlStart(String helpUrl, String title) {
1394
1395        return pageHtml(HTML_START, helpUrl, title);
1396    }
1397
1398    /**
1399     * Builds the start html of the page, including setting of DOCTYPE,
1400     * inserting a header with the content-type and choosing an individual style sheet.<p>
1401     *
1402     * @param title the title for the page
1403     * @param stylesheet the style sheet to include
1404     *
1405     * @return the start html of the page
1406     */
1407    public String htmlStartStyle(String title, String stylesheet) {
1408
1409        return pageHtmlStyle(HTML_START, title, stylesheet);
1410    }
1411
1412    /**
1413     * Displays the throwable on the error page and logs the error.<p>
1414     *
1415     * @param wp the workplace class
1416     * @param t the throwable to be displayed on the error page
1417     *
1418     * @throws JspException if the include of the error page jsp fails
1419     */
1420    public void includeErrorpage(CmsWorkplace wp, Throwable t) throws JspException {
1421
1422        CmsLog.getLog(wp).error(Messages.get().getBundle().key(Messages.ERR_WORKPLACE_DIALOG_0), t);
1423        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, wp);
1424        getJsp().getRequest().setAttribute(ATTRIBUTE_THROWABLE, t);
1425        getJsp().include(FILE_DIALOG_SCREEN_ERRORPAGE);
1426    }
1427
1428    /**
1429     * Returns the "isPopup" flag.<p>
1430     *
1431     * @return the "isPopup" flag
1432     */
1433    public boolean isPopup() {
1434
1435        return Boolean.valueOf(getParamIsPopup()).booleanValue();
1436    }
1437
1438    /**
1439     * Returns if the dialog is called in direct edit mode before the editor is opened.<p>
1440     *
1441     * @return true if the dialog is called in direct edit mode before the editor is opened
1442     */
1443    public boolean isPreEditor() {
1444
1445        return CmsPreEditorAction.isPreEditorMode(this);
1446    }
1447
1448    /**
1449     * Builds the start html of the page, including setting of DOCTYPE and
1450     * inserting a header with the content-type.<p>
1451     *
1452     * This overloads the default method of the parent class.<p>
1453     *
1454     * @param segment the HTML segment (START / END)
1455     * @param helpUrl the url for the online help to include on the page
1456     *
1457     * @return the start html of the page
1458     */
1459    @Override
1460    public String pageHtml(int segment, String helpUrl) {
1461
1462        return pageHtml(segment, helpUrl, null);
1463    }
1464
1465    /**
1466     * Builds the start html of the page, including setting of DOCTYPE and
1467     * inserting a header with the content-type.<p>
1468     *
1469     * This overloads the default method of the parent class.<p>
1470     *
1471     * @param segment the HTML segment (START / END)
1472     * @param helpUrl the url for the online help to include on the page
1473     * @param title the title for the page
1474     *
1475     * @return the start html of the page
1476     */
1477    public String pageHtml(int segment, String helpUrl, String title) {
1478
1479        if (segment == HTML_START) {
1480            String stylesheet = null;
1481            if (isPopup() && !useNewStyle()) {
1482                stylesheet = "popup.css";
1483            }
1484            StringBuffer result = new StringBuffer(pageHtmlStyle(segment, title, stylesheet));
1485            if (getSettings().isViewExplorer()) {
1486                result.append("<script  src=\"");
1487                result.append(getSkinUri());
1488                result.append("commons/explorer.js\"></script>\n");
1489            }
1490            result.append("<script >\n");
1491            result.append(dialogScriptSubmit());
1492            if (helpUrl != null) {
1493                result.append("if (top.head && top.head.helpUrl) {\n");
1494                result.append("\ttop.head.helpUrl=\"");
1495                result.append(helpUrl + "\";\n");
1496                result.append("}\n\n");
1497            }
1498            // the variable that may be set as path: if non-null this will be
1499            // used as path for the online help window. This is needed because there are pages
1500            // e.g. /administration/accounts/users/new  that perform a jsp - forward while leaving the
1501            // path parameter on the old page: no correct online help possible.
1502            result.append("var onlineHelpUriCustom = ");
1503            result.append(getOnlineHelpUriCustom());
1504            result.append(";\n");
1505
1506            result.append("</script>\n");
1507            return result.toString();
1508        } else {
1509            return super.pageHtml(segment, null);
1510        }
1511    }
1512
1513    /**
1514     * Set the custom mapping for the online help. <p>
1515     *
1516     * This value will be set to a javascript variable called onlineHelpUriCustom.
1517     * If it is set, the top.head javascript for the online help will use this value. <p>
1518     *
1519     * This method should be called from <code>{@link #initWorkplaceRequestValues(CmsWorkplaceSettings, HttpServletRequest)}</code>,
1520     * <code>{@link CmsWorkplace#initWorkplaceMembers(CmsJspActionElement)}</code>
1521     * or from the jsp if the dialog class is used for several actions.
1522     * It should be used whenever the online help mapping does not work (due to jsp - forwards).<p>
1523     *
1524     * @param uri the left hand value in mapping.properties for the online help pages
1525     */
1526    public void setOnlineHelpUriCustom(String uri) {
1527
1528        m_onlineHelpUriCustom = uri;
1529    }
1530
1531    /**
1532     * Sets the value of the action parameter.<p>
1533     *
1534     * @param value the value to set
1535     */
1536    public void setParamAction(String value) {
1537
1538        m_paramAction = value;
1539    }
1540
1541    /**
1542     * Sets the value of the close link parameter.<p>
1543     *
1544     * @param value the value to set
1545     */
1546    public void setParamCloseLink(String value) {
1547
1548        // ensure decoded chars are re-encoded again properly
1549
1550        m_paramCloseLink = value;
1551    }
1552
1553    /**
1554     * Sets the value of the dialog type parameter.<p>
1555     *
1556     * @param value the value to set
1557     */
1558    public void setParamDialogtype(String value) {
1559
1560        m_paramDialogtype = value;
1561    }
1562
1563    /**
1564     * Sets the value of the frame name parameter.<p>
1565     *
1566     * @param value the value to set
1567     */
1568    public void setParamFramename(String value) {
1569
1570        m_paramFrameName = value;
1571    }
1572
1573    /**
1574     * Sets the is popup parameter.<p>
1575     *
1576     * @param value the is popup parameter value
1577     */
1578    public void setParamIsPopup(String value) {
1579
1580        m_paramIsPopup = value;
1581    }
1582
1583    /**
1584     * Sets the value of the message parameter.<p>
1585     *
1586     * @param value the value to set
1587     */
1588    public void setParamMessage(String value) {
1589
1590        m_paramMessage = value;
1591    }
1592
1593    /**
1594     * Sets the value of the original parameters parameter.<p>
1595     *
1596     * @param paramOriginalParams the value of the original parameters parameter
1597     */
1598    public void setParamOriginalParams(String paramOriginalParams) {
1599
1600        m_paramOriginalParams = paramOriginalParams;
1601    }
1602
1603    /**
1604     * Sets the value of the preaction done parameter.<p>
1605     *
1606     * @param paramPreActionDone the value of the preaction done parameter
1607     */
1608    public void setParamPreActionDone(String paramPreActionDone) {
1609
1610        m_paramPreActionDone = paramPreActionDone;
1611    }
1612
1613    /**
1614     * Sets the value of the redirect flag parameter.<p>
1615     *
1616     * @param redirect the value of the redirect flag parameter
1617     */
1618    public void setParamRedirect(String redirect) {
1619
1620        m_paramRedirect = redirect;
1621    }
1622
1623    /**
1624     * Sets the value of the file parameter.<p>
1625     *
1626     * @param value the value to set
1627     */
1628    public void setParamResource(String value) {
1629
1630        m_paramResource = value;
1631    }
1632
1633    /**
1634     * Sets the value of the title parameter.<p>
1635     *
1636     * @param value the value to set
1637     */
1638    public void setParamTitle(String value) {
1639
1640        m_paramTitle = value;
1641    }
1642
1643    /**
1644     * Appends a space char. between tag attributes.<p>
1645     *
1646     * @param attribute a tag attribute
1647     *
1648     * @return the tag attribute with a leading space char
1649     */
1650    protected String appendDelimiter(String attribute) {
1651
1652        if (CmsStringUtil.isNotEmpty(attribute)) {
1653            if (!attribute.startsWith(" ")) {
1654                // add a delimiter space between the beginning button HTML and the button tag attributes
1655                return " " + attribute;
1656            } else {
1657                return attribute;
1658            }
1659        }
1660
1661        return "";
1662    }
1663
1664    /**
1665     * Returns ajax wait message.<p>
1666     *
1667     * @return html code
1668     */
1669    protected String buildAjaxWaitMessage() {
1670
1671        StringBuffer html = new StringBuffer(512);
1672        html.append("<table border='0' style='vertical-align:middle; height: 150px;'>\n");
1673        html.append("<tr><td width='40' align='center' valign='middle'><img src='");
1674        html.append(CmsWorkplace.getSkinUri());
1675        html.append("commons/wait.gif' id='ajaxreport-img' width='32' height='32' alt=''></td>\n");
1676        html.append("<td valign='middle'><span id='ajaxreport-txt' style='color: #000099; font-weight: bold;'>\n");
1677        html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_WAIT_0));
1678        html.append("</span><br></td></tr></table>\n");
1679        return html.toString();
1680    }
1681
1682    /**
1683     * Checks if the permissions of the current user on the resource to use in the dialog are sufficient.<p>
1684     *
1685     * Automatically generates a CmsMessageContainer object with an error message and stores it in the users session.<p>
1686     *
1687     * @param required the required permissions for the dialog
1688     * @param neededForFolder if true, the permissions are required for the parent folder of the resource (e.g. for editors)
1689     *
1690     * @return true if the permissions are sufficient, otherwise false
1691     */
1692    protected boolean checkResourcePermissions(CmsPermissionSet required, boolean neededForFolder) {
1693
1694        return checkResourcePermissions(
1695            required,
1696            neededForFolder,
1697            Messages.get().container(
1698                Messages.GUI_ERR_RESOURCE_PERMISSIONS_2,
1699                getParamResource(),
1700                required.getPermissionString()));
1701    }
1702
1703    /**
1704     * Checks if the permissions of the current user on the resource to use in the dialog are sufficient.<p>
1705     *
1706     * Automatically generates a CmsMessageContainer object with an error message and stores it in the users session.<p>
1707     *
1708     * @param required the required permissions for the dialog
1709     * @param neededForFolder if true, the permissions are required for the parent folder of the resource (e.g. for editors)
1710     * @param errorMessage the message container that is stored in the session in case the permissions are not sufficient
1711     *
1712     * @return true if the permissions are sufficient, otherwise false
1713     */
1714    protected boolean checkResourcePermissions(
1715        CmsPermissionSet required,
1716        boolean neededForFolder,
1717        CmsMessageContainer errorMessage) {
1718
1719        boolean hasPermissions = false;
1720        try {
1721            CmsResource res;
1722            if (neededForFolder) {
1723                // check permissions for the folder the resource is in
1724                res = getCms().readResource(CmsResource.getParentFolder(getParamResource()), CmsResourceFilter.ALL);
1725            } else {
1726                res = getCms().readResource(getParamResource(), CmsResourceFilter.ALL);
1727            }
1728            hasPermissions = getCms().hasPermissions(res, required, false, CmsResourceFilter.ALL);
1729        } catch (CmsException e) {
1730            // should usually never happen
1731            if (LOG.isInfoEnabled()) {
1732                LOG.info(e.getLocalizedMessage(), e);
1733            }
1734        }
1735
1736        if (!hasPermissions) {
1737            // store the error message in the users session
1738            getSettings().setErrorMessage(errorMessage);
1739        }
1740
1741        return hasPermissions;
1742    }
1743
1744    /**
1745     * Returns the full path of the current workplace folder.<p>
1746     *
1747     * @return the full path of the current workplace folder
1748     */
1749    protected String computeCurrentFolder() {
1750
1751        String currentFolder = getSettings().getExplorerResource();
1752        if (currentFolder == null) {
1753            // set current folder to root folder
1754            try {
1755                currentFolder = getCms().getSitePath(getCms().readFolder("/", CmsResourceFilter.IGNORE_EXPIRATION));
1756            } catch (CmsException e) {
1757                // can usually be ignored
1758                if (LOG.isInfoEnabled()) {
1759                    LOG.info(e.getLocalizedMessage(), e);
1760                }
1761                currentFolder = "/";
1762            }
1763        }
1764        if (!currentFolder.endsWith("/")) {
1765            // add folder separator to currentFolder
1766            currentFolder += "/";
1767        }
1768        return currentFolder;
1769    }
1770
1771    /**
1772     * Renders the HTML for a single input button of a specified type.<p>
1773     *
1774     * @param result a string buffer where the rendered HTML gets appended to
1775     * @param button a integer key to identify the button
1776     * @param attribute an optional string with possible tag attributes, or null
1777     */
1778    protected void dialogButtonsHtml(StringBuffer result, int button, String attribute) {
1779
1780        attribute = appendDelimiter(attribute);
1781
1782        switch (button) {
1783            case BUTTON_OK:
1784                result.append("<input name=\"ok\" value=\"");
1785                result.append(key(Messages.GUI_DIALOG_BUTTON_OK_0) + "\"");
1786                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1787                    result.append(" type=\"submit\"");
1788                } else {
1789                    result.append(" type=\"button\"");
1790                }
1791                result.append(" class=\"dialogbutton\"");
1792                result.append(attribute);
1793                result.append(">\n");
1794                break;
1795            case BUTTON_CANCEL:
1796                result.append("<input name=\"cancel\" type=\"button\" value=\"");
1797                result.append(key(Messages.GUI_DIALOG_BUTTON_CANCEL_0) + "\"");
1798                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1799                    result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\"");
1800                }
1801                result.append(" class=\"dialogbutton\"");
1802                result.append(attribute);
1803                result.append(">\n");
1804                break;
1805            case BUTTON_EDIT:
1806                result.append("<input name=\"ok\" value=\"");
1807                result.append(key(Messages.GUI_DIALOG_BUTTON_EDIT_0) + "\"");
1808                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1809                    result.append(" type=\"submit\"");
1810                } else {
1811                    result.append(" type=\"button\"");
1812                }
1813                result.append(" class=\"dialogbutton\"");
1814                result.append(attribute);
1815                result.append(">\n");
1816                break;
1817            case BUTTON_DISCARD:
1818                result.append("<input name=\"cancel\" type=\"button\" value=\"");
1819                result.append(key(Messages.GUI_DIALOG_BUTTON_DISCARD_0) + "\"");
1820                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1821                    result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\"");
1822                }
1823                result.append(" class=\"dialogbutton\"");
1824                result.append(attribute);
1825                result.append(">\n");
1826                break;
1827            case BUTTON_CLOSE:
1828                result.append("<input name=\"close\" type=\"button\" value=\"");
1829                result.append(key(Messages.GUI_DIALOG_BUTTON_CLOSE_0) + "\"");
1830                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1831                    result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\"");
1832                }
1833                result.append(" class=\"dialogbutton\"");
1834                result.append(attribute);
1835                result.append(">\n");
1836                break;
1837            case BUTTON_ADVANCED:
1838                result.append("<input name=\"advanced\" type=\"button\" value=\"");
1839                result.append(key(Messages.GUI_DIALOG_BUTTON_ADVANCED_0) + "\"");
1840                result.append(" class=\"dialogbutton\"");
1841                result.append(attribute);
1842                result.append(">\n");
1843                break;
1844            case BUTTON_SET:
1845                result.append("<input name=\"set\" type=\"button\" value=\"");
1846                result.append(key(Messages.GUI_DIALOG_BUTTON_SET_0) + "\"");
1847                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1848                    result.append(" onclick=\"submitAction('" + DIALOG_SET + "', form);\"");
1849                }
1850                result.append(" class=\"dialogbutton\"");
1851                result.append(attribute);
1852                result.append(">\n");
1853                break;
1854            case BUTTON_BACK:
1855                result.append("<input name=\"set\" type=\"button\" value=\"");
1856                result.append(key(Messages.GUI_DIALOG_BUTTON_BACK_0) + "\"");
1857                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1858                    result.append(" onclick=\"submitAction('" + DIALOG_BACK + "', form);\"");
1859                }
1860                result.append(" class=\"dialogbutton\"");
1861                result.append(attribute);
1862                result.append(">\n");
1863                break;
1864            case BUTTON_CONTINUE:
1865                result.append("<input name=\"set\" type=\"button\" value=\"");
1866                result.append(key(Messages.GUI_DIALOG_BUTTON_CONTINUE_0) + "\"");
1867                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1868                    result.append(" onclick=\"submitAction('" + DIALOG_CONTINUE + "', form);\"");
1869                }
1870                result.append(" class=\"dialogbutton\"");
1871                result.append(attribute);
1872                result.append(">\n");
1873                break;
1874            case BUTTON_DETAILS:
1875                result.append("<input name=\"details\" type=\"button\" value=\"");
1876                result.append(key(Messages.GUI_DIALOG_BUTTON_DETAIL_0) + "\"");
1877                result.append(" class=\"dialogbutton\"");
1878                result.append(attribute);
1879                result.append(">\n");
1880                break;
1881            default:
1882                // not a valid button code, just insert a warning in the HTML
1883                result.append("<!-- invalid button code: ");
1884                result.append(button);
1885                result.append(" -->\n");
1886        }
1887    }
1888
1889    /**
1890     * Returns the link URL to get back one folder in the administration view.<p>
1891     *
1892     * @return the link URL to get back one folder in the administration view
1893     */
1894    protected String getAdministrationBackLink() {
1895
1896        return CmsWorkplace.VFS_PATH_WORKPLACE
1897            + "action/administration_content_top.html"
1898            + "?sender="
1899            + CmsResource.getParentFolder(getJsp().getRequestContext().getFolderUri());
1900    }
1901
1902    /**
1903     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
1904     */
1905    @Override
1906    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
1907
1908        fillParamValues(request);
1909        if (DIALOG_CANCEL.equals(getParamAction())) {
1910            setAction(ACTION_CANCEL);
1911        }
1912    }
1913
1914    /**
1915     * Opens the launch pad view.<p>
1916     *
1917     * @throws JspException in case writing to the JSP output stream fails
1918     */
1919    protected void openLaunchpad() throws JspException {
1920
1921        try {
1922            openWorkplaceLink(CmsVaadinUtils.getWorkplaceLink(CmsAppHierarchyConfiguration.APP_ID));
1923        } catch (Exception e) {
1924            // forward failed
1925            throw new JspException(e.getMessage(), e);
1926        }
1927    }
1928
1929    /**
1930     * Opens a workplace UI link in the top frame.<p>
1931     *
1932     * @param workplaceLink the workplace link to open
1933     *
1934     * @throws IOException in case writing to the JSP output stream fails
1935     */
1936    protected void openWorkplaceLink(String workplaceLink) throws IOException {
1937
1938        // in case the close link points to the new workplace, make sure to set the new location on the top frame
1939        JspWriter out = getJsp().getJspContext().getOut();
1940        try {
1941            out.write(
1942                "<html><head><script >top.location.href=\""
1943                    + workplaceLink
1944                    + "\";</script></head>\n");
1945            out.write("</html>\n");
1946        } finally {
1947            out.close();
1948        }
1949    }
1950
1951    /**
1952     * Sets the action value.<p>
1953     *
1954     * @param value the action value
1955     */
1956    protected void setAction(int value) {
1957
1958        m_action = value;
1959    }
1960}