001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.workplace.commons;
029
030import org.opencms.configuration.CmsDefaultUserSettings;
031import org.opencms.db.CmsPublishList;
032import org.opencms.file.CmsResource;
033import org.opencms.file.CmsResourceFilter;
034import org.opencms.jsp.CmsJspActionElement;
035import org.opencms.lock.CmsLock;
036import org.opencms.lock.CmsLockFilter;
037import org.opencms.main.CmsException;
038import org.opencms.main.CmsLog;
039import org.opencms.main.OpenCms;
040import org.opencms.report.CmsHtmlReport;
041import org.opencms.security.CmsPermissionSet;
042import org.opencms.security.CmsRole;
043import org.opencms.util.CmsStringUtil;
044import org.opencms.util.CmsUUID;
045import org.opencms.workplace.CmsMultiDialog;
046import org.opencms.workplace.CmsWorkplaceSettings;
047
048import java.util.ArrayList;
049import java.util.Iterator;
050import java.util.List;
051
052import javax.servlet.http.HttpServletRequest;
053import javax.servlet.http.HttpServletResponse;
054import javax.servlet.jsp.JspException;
055import javax.servlet.jsp.PageContext;
056
057import org.apache.commons.logging.Log;
058
059/**
060 * Creates the dialogs for publishing a project or a resource.<p>
061 *
062 * The following files use this class:
063 * <ul>
064 * <li>/commons/publishproject.jsp
065 * <li>/commons/publishresource.jsp
066 * </ul>
067 * <p>
068 *
069 * @since 6.0.0
070 */
071public class CmsPublishProject extends CmsMultiDialog {
072
073    /** Value for the action: delete the resource. */
074    public static final int ACTION_PUBLISH = 110;
075
076    /** Value for the action: resources confirmed. */
077    public static final int ACTION_RESOURCES_CONFIRMED = 111;
078
079    /** Request parameter value for the action: dialog resources confirmed. */
080    public static final String DIALOG_RESOURCES_CONFIRMED = "resourcesconfirmed";
081
082    /** The dialog type. */
083    public static final String DIALOG_TYPE = "publishproject";
084
085    /** Request parameter name for the directpublish parameter. */
086    public static final String PARAM_DIRECTPUBLISH = "directpublish";
087
088    /** Request parameter name for the publishsiblings parameter. */
089    public static final String PARAM_PUBLISHSIBLINGS = "publishsiblings";
090
091    /** Request parameter name for the relatedresources parameter. */
092    public static final String PARAM_RELATEDRESOURCES = "relatedresources";
093
094    /** Request parameter name for the subresources parameter. */
095    public static final String PARAM_SUBRESOURCES = "subresources";
096
097    /** The log object for this class. */
098    private static final Log LOG = CmsLog.getLog(CmsPublishProject.class);
099
100    /** Parameter value for the direct publish flag. */
101    private String m_paramDirectpublish;
102
103    /** Parameter value for the progress key. */
104    private String m_paramProgresskey;
105
106    /** Parameter value for the project id. */
107    private String m_paramProjectid;
108
109    /** Parameter value for the project name. */
110    private String m_paramProjectname;
111
112    /** Parameter value for the publish siblings flag. */
113    private String m_paramPublishsiblings;
114
115    /** Parameter value for the publish related resources flag. */
116    private String m_paramRelatedresources;
117
118    /** Parameter value for the publish subresources flag. */
119    private String m_paramSubresources;
120
121    /** The progress bar for the dialog. */
122    private CmsProgressWidget m_progress;
123
124    /**
125     * Public constructor.<p>
126     *
127     * @param jsp an initialized JSP action element
128     */
129    public CmsPublishProject(CmsJspActionElement jsp) {
130
131        super(jsp);
132    }
133
134    /**
135     * Public constructor with JSP variables.<p>
136     *
137     * @param context the JSP page context
138     * @param req the JSP request
139     * @param res the JSP response
140     */
141    public CmsPublishProject(PageContext context, HttpServletRequest req, HttpServletResponse res) {
142
143        this(new CmsJspActionElement(context, req, res));
144    }
145
146    /**
147     * @see org.opencms.workplace.CmsDialog#actionCloseDialog()
148     */
149    @Override
150    public void actionCloseDialog() throws JspException {
151
152        CmsProgressThread thread = CmsProgressWidget.getProgressThread(getParamProgresskey());
153        if (thread != null) {
154            thread.interrupt();
155            CmsProgressWidget.removeProgressThread(thread.getKey());
156        }
157
158        super.actionCloseDialog();
159    }
160
161    /**
162     * Performs the publish action, will be called by the JSP page.<p>
163     *
164     * @throws JspException if problems including sub-elements occur
165     */
166    public void actionPublish() throws JspException {
167
168        try {
169            boolean isFolder = false;
170            if (!isMultiOperation()) {
171                if (isDirectPublish()) {
172                    isFolder = getCms().readResource(getParamResource(), CmsResourceFilter.ALL).isFolder();
173                }
174            }
175            if (performDialogOperation()) {
176                // if no exception is caused and "true" is returned publish operation was successful
177                if (isMultiOperation() || isFolder) {
178                    // set request attribute to reload the explorer tree view
179                    List<String> folderList = new ArrayList<String>();
180                    folderList.add(CmsResource.getParentFolder(getResourceList().get(0)));
181                    Iterator<String> it = getResourceList().iterator();
182                    while (it.hasNext()) {
183                        String res = it.next();
184                        if (CmsResource.isFolder(res)) {
185                            folderList.add(res);
186                        }
187                    }
188                    getJsp().getRequest().setAttribute(REQUEST_ATTRIBUTE_RELOADTREE, folderList);
189                }
190                actionCloseDialog();
191            } else {
192                // "false" returned, display "please wait" screen
193                getJsp().include(FILE_DIALOG_SCREEN_WAIT);
194            }
195        } catch (Throwable e) {
196            // prepare common message part
197            includeErrorpage(this, e);
198        }
199    }
200
201    /**
202     * Returns the html for the confirmation message.<p>
203     *
204     * @return the html for the confirmation message
205     */
206    public String buildConfirmation() {
207
208        StringBuffer result = new StringBuffer(512);
209
210        result.append("<p><div id='conf-msg'>\n");
211        if (!isDirectPublish()) {
212            result.append(key(Messages.GUI_PUBLISH_PROJECT_CONFIRMATION_1, new Object[] {getProjectname()}));
213        } else {
214            boolean isFolder = false;
215            if (!isMultiOperation()) {
216                try {
217                    isFolder = getCms().readResource(getParamResource(), CmsResourceFilter.ALL).isFolder();
218                } catch (CmsException e) {
219                    // ignore
220                }
221            }
222            if (isMultiOperation() || isFolder || (hasSiblings() && hasCorrectLockstate())) {
223                result.append(key(Messages.GUI_PUBLISH_MULTI_CONFIRMATION_0));
224            } else {
225                result.append(key(Messages.GUI_PUBLISH_CONFIRMATION_0));
226            }
227        }
228        result.append("\n</div></p>\n");
229        return result.toString();
230    }
231
232    /**
233     * Returns the html code to build the confirmation messages.<p>
234     *
235     * @return html code
236     */
237    @Override
238    public String buildLockConfirmationMessageJS() {
239
240        StringBuffer html = new StringBuffer(512);
241        html.append("<script ><!--\n");
242        html.append("function setConfirmationMessage(locks, blockinglocks) {\n");
243        html.append("\tvar confMsg = document.getElementById('conf-msg');\n");
244        html.append("\tif (locks > -1) {\n");
245        html.append("\t\tdocument.getElementById('butClose').className = 'hide';\n");
246        html.append("\t\tdocument.getElementById('butContinue').className = '';\n");
247        html.append("\t\tif (locks > 0) {\n");
248        html.append("\t\t\tshowAjaxReportContent();\n");
249        html.append("\t\t\tconfMsg.innerHTML = '");
250        html.append(key(Messages.GUI_PUBLISH_UNLOCK_CONFIRMATION_0));
251        html.append("';\n");
252        html.append("\t\t} else {\n");
253        html.append("\t\tshowAjaxOk();\n");
254        html.append("\t\t\tconfMsg.innerHTML = '");
255        html.append(key(Messages.GUI_PUBLISH_NO_LOCKS_CONFIRMATION_0));
256        html.append("';\n");
257        html.append("\t\t}\n");
258        html.append("\t} else {\n");
259        html.append("\t\tdocument.getElementById('butClose').className = '';\n");
260        html.append("\t\tdocument.getElementById('butContinue').className = 'hide';\n");
261        html.append("\t\tconfMsg.innerHTML = '");
262        html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_WAIT_0));
263        html.append("';\n");
264        html.append("\t}\n");
265        html.append("}\n");
266        html.append("// -->\n");
267        html.append("</script>\n");
268        return html.toString();
269    }
270
271    /**
272     * Returns the html code to build the lock dialog.<p>
273     *
274     * @return html code
275     *
276     * @throws CmsException if something goes wrong
277     */
278    public String buildLockDialog() throws CmsException {
279
280        CmsLockFilter nonBlockingFilter = CmsLockFilter.FILTER_ALL;
281        nonBlockingFilter = nonBlockingFilter.filterLockableByUser(getCms().getRequestContext().getCurrentUser());
282        nonBlockingFilter = nonBlockingFilter.filterSharedExclusive();
283        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParamProjectid())) {
284            nonBlockingFilter = nonBlockingFilter.filterProject(new CmsUUID(getParamProjectid()));
285        }
286        return org.opencms.workplace.commons.CmsLock.buildLockDialog(
287            this,
288            nonBlockingFilter,
289            getBlockingFilter(),
290            0,
291            true);
292    }
293
294    /**
295     * @see org.opencms.workplace.CmsMultiDialog#buildLockHeaderBox()
296     */
297    @Override
298    public String buildLockHeaderBox() throws CmsException {
299
300        if (isDirectPublish()) {
301            return super.buildLockHeaderBox();
302        }
303        StringBuffer html = new StringBuffer(512);
304        // include resource info
305        html.append(dialogBlockStart(null));
306        html.append(key(org.opencms.workplace.Messages.GUI_LABEL_PROJECT_0));
307        html.append(": ");
308        html.append(getProjectname());
309        html.append(dialogBlockEnd());
310        return html.toString();
311    }
312
313    /**
314     * Override to display additional options in the lock dialog.<p>
315     *
316     * @return html code to display additional options
317     */
318    public String buildPublishOptions() {
319
320        // show only for direct publish actions
321        StringBuffer result = new StringBuffer(128);
322        boolean showOptionSiblings = (isMultiOperation()
323            || isOperationOnFolder()
324            || (isDirectPublish() && hasSiblings() && hasCorrectLockstate()));
325        boolean showOptionSubresources = (isMultiOperation() || isOperationOnFolder());
326
327        result.append("<p>");
328        if (showOptionSiblings) {
329            // show only for multi resource operation or if resource has siblings and correct lock state
330            if (!isMultiOperation() && !isOperationOnFolder()) {
331                result.append(key(Messages.GUI_DELETE_WARNING_SIBLINGS_0));
332                result.append("<br>");
333            }
334            result.append("<input type='checkbox' name='");
335            result.append(PARAM_PUBLISHSIBLINGS);
336            result.append("' value='true' onclick=\"reloadReport();\"");
337            if (Boolean.valueOf(getParamPublishsiblings()).booleanValue()) {
338                result.append(" checked='checked'");
339            }
340            result.append(">&nbsp;");
341            result.append(key(Messages.GUI_PUBLISH_ALLSIBLINGS_0));
342            result.append("<br>\n");
343        } else {
344            result.append("<input type='hidden' name='");
345            result.append(PARAM_PUBLISHSIBLINGS);
346            result.append("' value='");
347            result.append(Boolean.valueOf(getParamPublishsiblings()));
348            result.append("'");
349            if (Boolean.valueOf(getParamPublishsiblings()).booleanValue()) {
350                result.append(" checked='checked'");
351            }
352            result.append(">\n");
353        }
354        if (showOptionSubresources) {
355            // at least one folder is selected, show "publish subresources" checkbox
356            result.append("<input type='checkbox' name='");
357            result.append(PARAM_SUBRESOURCES);
358            result.append("' value='true' onclick=\"reloadReport();\"");
359            if (Boolean.valueOf(getParamSubresources()).booleanValue()) {
360                result.append(" checked='checked'");
361            }
362            result.append(">&nbsp;");
363            if (isMultiOperation()) {
364                result.append(key(Messages.GUI_PUBLISH_MULTI_SUBRESOURCES_0));
365            } else {
366                result.append(key(Messages.GUI_PUBLISH_SUBRESOURCES_0));
367            }
368            result.append("<br>\n");
369        } else {
370            result.append("<input type='hidden' name='");
371            result.append(PARAM_SUBRESOURCES);
372            result.append("' value='");
373            result.append(Boolean.valueOf(getParamSubresources()));
374            result.append("'");
375            if (Boolean.valueOf(getParamSubresources()).booleanValue()) {
376                result.append(" checked='checked'");
377            }
378            result.append(">\n");
379        }
380        // code for the 'publish related resources' button
381        boolean disabled = false;
382        if ((OpenCms.getWorkplaceManager().getDefaultUserSettings().getPublishRelatedResources() == CmsDefaultUserSettings.PUBLISH_RELATED_RESOURCES_MODE_FORCE)
383            && !OpenCms.getRoleManager().hasRole(getCms(), CmsRole.VFS_MANAGER)) {
384            disabled = true;
385        }
386        result.append("<input type='checkbox' name='");
387        result.append(PARAM_RELATEDRESOURCES);
388        result.append("' value='true' onclick=\"reloadReport();\"");
389        if (Boolean.valueOf(getParamRelatedresources()).booleanValue()) {
390            result.append(" checked='checked'");
391        }
392        if (disabled) {
393            result.append(" disabled='disabled'");
394        }
395        result.append(">&nbsp;");
396        result.append(key(Messages.GUI_PUBLISH_RELATED_RESOURCES_0));
397        result.append("<br>\n");
398        result.append("</p>\n");
399        return result.toString();
400    }
401
402    /**
403     * Returns the list of the resources to publish with broken relations.<p>
404     *
405     * @return the list of the resources to publish with broken relations
406     */
407    public CmsPublishBrokenRelationsList getBrokenRelationsList() {
408
409        return new CmsPublishBrokenRelationsList(getJsp(), getParentFolder());
410    }
411
412    /**
413     * Returns if a resource will be directly published.<p>
414     *
415     * @return <code>"true"</code> if a resource will be directly published
416     */
417    public String getParamDirectpublish() {
418
419        return m_paramDirectpublish;
420    }
421
422    /**
423     * @see org.opencms.workplace.CmsDialog#getParamFramename()
424     */
425    @Override
426    public String getParamFramename() {
427
428        String fn = super.getParamFramename();
429        // to correctly return after publish project
430        if ((fn == null) && !isDirectPublish()) {
431            fn = "body";
432        }
433        return fn;
434    }
435
436    /**
437     * Returns the value for the progress key.<p>
438     *
439     * @return the value for the progress key
440     */
441    public String getParamProgresskey() {
442
443        return m_paramProgresskey;
444    }
445
446    /**
447     * Returns the value of the project id which will be published.<p>
448     *
449     * @return the String value of the project id
450     */
451    public String getParamProjectid() {
452
453        return m_paramProjectid;
454    }
455
456    /**
457     * Returns the value of the project name which will be published.<p>
458     *
459     * @return the String value of the project name
460     */
461    public String getParamProjectname() {
462
463        return m_paramProjectname;
464    }
465
466    /**
467     * Returns if siblings of the resource should be published.<p>
468     *
469     * @return <code>"true"</code> (String) if siblings of the resource should be published
470     */
471    public String getParamPublishsiblings() {
472
473        return m_paramPublishsiblings;
474    }
475
476    /**
477     * Returns the value of the related resources parameter.<p>
478     *
479     * @return the value of the related resources parameter
480     */
481    public String getParamRelatedresources() {
482
483        return m_paramRelatedresources;
484    }
485
486    /**
487     * Returns the value of the subresources parameter.<p>
488     *
489     * @return the value of the sub resources parameter
490     */
491    public String getParamSubresources() {
492
493        return m_paramSubresources;
494    }
495
496    /**
497     * Returns the progress bar for the dialog.<p>
498     *
499     * @return the progress bar for the dialog
500     */
501    public CmsProgressWidget getProgress() {
502
503        return m_progress;
504    }
505
506    /**
507     * Unlocks all selected resources, will be called by the JSP page.<p>
508     *
509     * @return <code>true</code> if everything went ok
510     *
511     * @throws JspException if there is some problem including the error page
512     */
513    public CmsPublishList getPublishList() throws JspException {
514
515        CmsPublishList publishList = null;
516        if (isDirectPublish()) {
517            // get the offline resource(s) in direct publish mode
518            List<CmsResource> publishResources = new ArrayList<CmsResource>(getResourceList().size());
519            Iterator<String> i = getResourceList().iterator();
520            while (i.hasNext()) {
521                String resName = i.next();
522                try {
523                    publishResources.add(getCms().readResource(resName, CmsResourceFilter.ALL));
524                } catch (CmsException e) {
525                    addMultiOperationException(e);
526                }
527            }
528            try {
529                boolean publishSubResources = Boolean.valueOf(getParamSubresources()).booleanValue();
530                boolean publishSiblings = Boolean.valueOf(getParamPublishsiblings()).booleanValue();
531                // create publish list for direct publish
532                publishList = OpenCms.getPublishManager().getPublishList(
533                    getCms(),
534                    publishResources,
535                    publishSiblings,
536                    publishSubResources);
537            } catch (CmsException e) {
538                addMultiOperationException(e);
539            }
540        } else {
541            try {
542                // be careful #getParamProjectid() is always the current project
543                publishList = OpenCms.getPublishManager().getPublishList(getCms());
544            } catch (CmsException e) {
545                addMultiOperationException(e);
546            }
547        }
548        try {
549            // throw exception for errors unlocking resources
550            checkMultiOperationException(Messages.get(), Messages.ERR_PUBLISH_LIST_CREATION_0);
551        } catch (Throwable e) {
552            publishList = null;
553            // error while unlocking resources, show error screen
554            includeErrorpage(this, e);
555        }
556        getSettings().setPublishList(publishList);
557        return publishList;
558    }
559
560    /**
561     * Returns the list with the resources to publish.<p>
562     *
563     * @return the list with the resources to publish
564     *
565     * @throws JspException if creation of publish list fails
566     */
567    public CmsPublishResourcesList getPublishResourcesList() throws JspException {
568
569        if (getPublishList() != null) {
570            return new CmsPublishResourcesList(
571                getJsp(),
572                getParentFolder(),
573                Boolean.valueOf(getParamRelatedresources()).booleanValue());
574        }
575
576        return null;
577    }
578
579    /**
580     * Returns <code>true</code> if the resources to be published will generate broken links.<p>
581     *
582     * @return <code>true</code> if the resources to be published will generate broken links
583     */
584    public boolean hasBrokenLinks() {
585
586        //        CmsPublishBrokenRelationsList list = new CmsPublishBrokenRelationsList(getJsp(), getParentFolder());
587        //        list.refreshList();
588
589        return (getBrokenRelationsList().getList().getTotalSize() > 0);
590    }
591
592    /**
593     * Returns <code>true</code> if the current user is allowed
594     * to publish the selected resources.<p>
595     *
596     * @return <code>true</code> if the current user is allowed
597     *          to publish the selected resources
598     */
599    public boolean isCanPublish() {
600
601        return OpenCms.getWorkplaceManager().getDefaultUserSettings().isAllowBrokenRelations()
602            || OpenCms.getRoleManager().hasRole(getCms(), CmsRole.VFS_MANAGER);
603    }
604
605    /**
606     * Returns <code>true</code> if the selection has blocking locks.<p>
607     *
608     * @return <code>true</code> if the selection has blocking locks
609     */
610    public boolean isLockStateOk() {
611
612        org.opencms.workplace.commons.CmsLock lockDialog = new org.opencms.workplace.commons.CmsLock(getJsp());
613        lockDialog.setParamIncluderelated(CmsStringUtil.TRUE);
614        lockDialog.setBlockingFilter(getBlockingFilter());
615        if (!isDirectPublish()) {
616            lockDialog.setParamResource("/");
617        }
618        if (!lockDialog.getBlockingLockedResources().isEmpty()) {
619            // blocking locks found, so show them
620            return false;
621        }
622        if (!isDirectPublish()) {
623            // is publish project operation no resource iteration possible
624            return true;
625        }
626
627        // flag to indicate that all resources are exclusive locked
628        boolean locked = true;
629        // flag to indicate that all resources are unlocked
630        boolean unlocked = true;
631
632        Iterator<String> i = getResourceList().iterator();
633        while (i.hasNext()) {
634            String resName = i.next();
635            try {
636                CmsLock lock = getCms().getLock(getCms().readResource(resName, CmsResourceFilter.ALL));
637                if (!lock.isUnlocked()) {
638                    unlocked = false;
639                    if (locked
640                        && !lock.isOwnedInProjectBy(
641                            getCms().getRequestContext().getCurrentUser(),
642                            getCms().getRequestContext().getCurrentProject())) {
643                        // locks of another users or locked in another project are blocking
644                        locked = false;
645                    }
646                }
647            } catch (CmsException e) {
648                // error reading a resource, should usually never happen
649                if (LOG.isErrorEnabled()) {
650                    LOG.error(e.getLocalizedMessage(), e);
651                }
652            }
653        }
654        return locked || unlocked;
655    }
656
657    /**
658     * Sets if a resource will be directly published.<p>
659     *
660     * @param value <code>"true"</code> (String) if a resource will be directly published
661     */
662    public void setParamDirectpublish(String value) {
663
664        m_paramDirectpublish = value;
665    }
666
667    /**
668     * Sets the value for the progress key.<p>
669     *
670     * @param value the value for the progress key to set
671     */
672    public void setParamProgresskey(String value) {
673
674        m_paramProgresskey = value;
675    }
676
677    /**
678     * Sets the value of the project id which will be published.<p>
679     *
680     * @param value the String value of the project id
681     */
682    public void setParamProjectid(String value) {
683
684        m_paramProjectid = value;
685    }
686
687    /**
688     * Sets the value of the project name which will be published.<p>
689     *
690     * @param value the String value of the project name
691     */
692    public void setParamProjectname(String value) {
693
694        m_paramProjectname = value;
695    }
696
697    /**
698     * Sets if siblings of the resource should be published.<p>
699     *
700     * @param value <code>"true"</code> (String) if siblings of the resource should be published
701     */
702    public void setParamPublishsiblings(String value) {
703
704        m_paramPublishsiblings = value;
705    }
706
707    /**
708     * Sets the value of the related resources parameter.<p>
709     *
710     * @param relatedResources the value of the related resources parameter
711     */
712    public void setParamRelatedresources(String relatedResources) {
713
714        m_paramRelatedresources = relatedResources;
715    }
716
717    /**
718     * Sets the value of the subresources parameter.<p>
719     *
720     * @param paramSubresources the value of the subresources parameter
721     */
722    public void setParamSubresources(String paramSubresources) {
723
724        m_paramSubresources = paramSubresources;
725    }
726
727    /**
728     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
729     */
730    @Override
731    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
732
733        // fill the parameter values in the get/set methods
734        fillParamValues(request);
735        // set the dialog type
736        setParamDialogtype(DIALOG_TYPE);
737
738        m_progress = new CmsProgressWidget(getJsp());
739        m_progress.setWidth("300px");
740
741        // set the publishing type: publish project or direct publish
742        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParamResource()) || isMultiOperation()) {
743            setParamDirectpublish(CmsStringUtil.TRUE);
744        }
745        // set default options
746        if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamAction()) || DIALOG_INITIAL.equals(getParamAction())) {
747            // siblings option. set to the default value defined in the opencms-workplace.xml
748            setParamPublishsiblings(String.valueOf(getSettings().getUserSettings().getDialogPublishSiblings()));
749            // sub resources option. default value is true
750            setParamSubresources(Boolean.TRUE.toString());
751            // related resources option.
752            String defValue = CmsStringUtil.TRUE;
753            if (OpenCms.getWorkplaceManager().getDefaultUserSettings().getPublishRelatedResources() == CmsDefaultUserSettings.PUBLISH_RELATED_RESOURCES_MODE_FALSE) {
754                defValue = CmsStringUtil.FALSE;
755            }
756            setParamRelatedresources(defValue);
757        }
758
759        // set the action for the JSP switch
760        if (DIALOG_TYPE.equals(getParamAction())) {
761            setAction(ACTION_PUBLISH);
762        } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) {
763            setAction(ACTION_LOCKS_CONFIRMED);
764        } else if (DIALOG_RESOURCES_CONFIRMED.equals(getParamAction())) {
765            setAction(ACTION_RESOURCES_CONFIRMED);
766
767            // merge publish list with related resources if needed
768            CmsPublishList publishList = getSettings().getPublishList();
769            if (publishList == null) { // this may happen if the user has not publish permissions (with multi selection)
770                // no publish permissions for the resource, set cancel action to close dialog
771                setAction(ACTION_CANCEL);
772                return;
773            }
774            if (Boolean.valueOf(getParamRelatedresources()).booleanValue() && publishList.isDirectPublish()) {
775                try {
776                    // try to find the publish list with related related resources in the progress thread
777                    CmsProgressThread thread = CmsProgressWidget.getProgressThread(getParamProgresskey());
778                    CmsPublishList storedList = null;
779                    if (thread != null) {
780                        storedList = ((CmsPublishResourcesList)thread.getList()).getPublishList();
781                    }
782
783                    if (storedList == null) {
784                        CmsPublishList relResources = OpenCms.getPublishManager().getRelatedResourcesToPublish(
785                            getCms(),
786                            publishList);
787                        publishList = OpenCms.getPublishManager().mergePublishLists(
788                            getCms(),
789                            publishList,
790                            relResources);
791                    } else {
792                        publishList = storedList;
793                    }
794
795                    getSettings().setPublishList(publishList);
796                } catch (CmsException e) {
797                    // should never happen
798                    if (LOG.isErrorEnabled()) {
799                        LOG.error(e.getLocalizedMessage(), e);
800                    }
801                }
802            }
803
804            // start the progress
805            CmsProgressWidget.removeProgressThread(getProgress().getKey());
806            getProgress().startProgress(getBrokenRelationsList());
807
808            // wait to see if already finished
809            synchronized (this) {
810                try {
811                    wait(500);
812                } catch (InterruptedException e) {
813                    // ignore
814                }
815            }
816
817            CmsProgressThread thread = CmsProgressWidget.getProgressThread(getProgress().getKey());
818            if ((!thread.isAlive()) && (thread.getList().getList().getTotalSize() == 0)) {
819                // skip broken links confirmation screen
820                setAction(ACTION_PUBLISH);
821            }
822
823        } else if (DIALOG_WAIT.equals(getParamAction())) {
824            setAction(ACTION_WAIT);
825        } else if (DIALOG_CANCEL.equals(getParamAction())) {
826            setAction(ACTION_CANCEL);
827        } else {
828            setAction(ACTION_DEFAULT);
829
830            // set parameters depending on publishing type
831            if (isDirectPublish()) {
832                // check the required permissions to publish the resource directly
833                if (!getCms().isManagerOfProject()
834                    && !checkResourcePermissions(CmsPermissionSet.ACCESS_DIRECT_PUBLISH, false)) {
835                    // no publish permissions for the single resource, set cancel action to close dialog
836                    setAction(ACTION_CANCEL);
837                    return;
838                }
839                // add the title for the direct publish dialog
840                setDialogTitle(Messages.GUI_PUBLISH_RESOURCE_1, Messages.GUI_PUBLISH_MULTI_2);
841            } else {
842                // add the title for the publish project dialog
843                setParamTitle(key(Messages.GUI_PUBLISH_PROJECT_0));
844                // determine the project id and name for publishing
845                computePublishProject();
846                // determine target to close the report
847            }
848            // if lock state if not as expected
849            if (isLockStateOk()) { // this may take a while :(
850                // skip lock confirmation screen
851                setAction(ACTION_LOCKS_CONFIRMED);
852            }
853        }
854    }
855
856    /**
857     * @see org.opencms.workplace.CmsMultiDialog#performDialogOperation()
858     */
859    @Override
860    protected boolean performDialogOperation() throws CmsException {
861
862        CmsPublishList publishList = getSettings().getPublishList();
863        if (publishList == null) {
864            throw new CmsException(
865                Messages.get().container(org.opencms.db.Messages.ERR_GET_PUBLISH_LIST_PROJECT_1, getProjectname()));
866        }
867        OpenCms.getPublishManager().publishProject(
868            getCms(),
869            new CmsHtmlReport(getLocale(), getCms().getRequestContext().getSiteRoot()),
870            publishList);
871        // wait 2 seconds, may be it finishes fast
872        OpenCms.getPublishManager().waitWhileRunning(1500);
873        return true;
874    }
875
876    /**
877     * Determine the right project id and name if no request parameter "projectid" is given.<p>
878     */
879    private void computePublishProject() {
880
881        String projectId = getParamProjectid();
882        CmsUUID id;
883        if (CmsStringUtil.isEmptyOrWhitespaceOnly(projectId)) {
884            // projectid not found in request parameter,
885            id = getCms().getRequestContext().getCurrentProject().getUuid();
886            setParamProjectname(getCms().getRequestContext().getCurrentProject().getName());
887            setParamProjectid("" + id);
888        } else {
889            id = new CmsUUID(projectId);
890            try {
891                setParamProjectname(getCms().readProject(id).getName());
892            } catch (CmsException e) {
893                LOG.error(Messages.get().getBundle().key(Messages.LOG_SET_PROJECT_NAME_FAILED_0), e);
894            }
895        }
896    }
897
898    /**
899     * Returns the filter to identify blocking locks.<p>
900     *
901     * @return the filter to identify blocking locks
902     */
903    private CmsLockFilter getBlockingFilter() {
904
905        CmsLockFilter blockingFilter = CmsLockFilter.FILTER_ALL;
906        blockingFilter = blockingFilter.filterNotLockableByUser(getCms().getRequestContext().getCurrentUser());
907        if (!isDirectPublish()) {
908            blockingFilter = blockingFilter.filterProject(new CmsUUID(getParamProjectid()));
909        }
910        return blockingFilter;
911    }
912
913    /**
914     * Returns the parent folder for the publish process.<p>
915     *
916     * @return the parent folder for the publish process
917     */
918    private String getParentFolder() {
919
920        String relativeTo;
921        if (isDirectPublish()) {
922            relativeTo = CmsResource.getParentFolder(getResourceList().get(0));
923        } else {
924            relativeTo = getCms().getRequestContext().getSiteRoot() + "/";
925        }
926        return relativeTo;
927    }
928
929    /**
930     * Returns the project name.<p>
931     *
932     * @return the project name
933     */
934    private String getProjectname() {
935
936        CmsUUID id = new CmsUUID(getParamProjectid());
937        try {
938            return getCms().readProject(id).getName();
939        } catch (CmsException e) {
940            LOG.error(Messages.get().getBundle().key(Messages.LOG_SET_PROJECT_NAME_FAILED_0), e);
941        }
942        return "-error-";
943    }
944
945    /**
946     * Returns <code>false</code> if this is a publish project operation.<p>
947     *
948     * @return <code>true</code> if this is a direct publish operation
949     */
950    private boolean isDirectPublish() {
951
952        if (getParamDirectpublish() != null) {
953            return Boolean.valueOf(getParamDirectpublish()).booleanValue();
954        }
955        return getDialogUri().endsWith("publishresource.jsp");
956    }
957}