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, 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.editors.directedit;
029
030import org.opencms.cache.CmsMemoryObjectCache;
031import org.opencms.file.CmsFile;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsProperty;
034import org.opencms.file.CmsPropertyDefinition;
035import org.opencms.i18n.CmsEncoder;
036import org.opencms.main.CmsException;
037import org.opencms.main.CmsLog;
038import org.opencms.main.OpenCms;
039import org.opencms.util.CmsMacroResolver;
040import org.opencms.workplace.CmsWorkplace;
041import org.opencms.workplace.editors.Messages;
042
043import javax.servlet.jsp.JspException;
044import javax.servlet.jsp.PageContext;
045
046import org.apache.commons.logging.Log;
047
048/**
049 * Provider for the OpenCms default graphical "direct edit" buttons.<p>
050 *
051 * Since OpenCms version 6.2.3,
052 * this provider is configured as the standard direct edit provider in a common OpenCms installation.<p>
053 *
054 * This provider DOES NOT support {@link CmsDirectEditMode#MANUAL} mode.<p>
055 *
056 * @since 6.2.3
057 */
058public class CmsDirectEditDefaultProvider extends A_CmsDirectEditProvider {
059
060    /** The log object for this class. */
061    private static final Log LOG = CmsLog.getLog(CmsDirectEditDefaultProvider.class);
062
063    /** Indicates the permissions for the last element the was opened. */
064    protected int m_lastPermissionMode;
065
066    /** The include file used by this provider. */
067    private String m_headerInclude;
068
069    /**
070     * Returns the end HTML for a disabled direct edit button.<p>
071     *
072     * @return the end HTML for a disabled direct edit button
073     */
074    public String endDirectEditDisabled() {
075
076        return "</div>\n<!-- EDIT BLOCK END (DISABLED) -->\n";
077    }
078
079    /**
080     * Returns the end HTML for an enabled direct edit button.<p>
081     *
082     * @return the end HTML for an enabled direct edit button
083     */
084    public String endDirectEditEnabled() {
085
086        return "</div>\n<!-- EDIT BLOCK END (ENABLED) -->\n";
087    }
088
089    /**
090     * Returns the direct edit include HTML to insert in the page beginning.<p> t
091     *
092     * @param params the parameters for the direct edit includes
093     *
094     * @return the direct edit include HTML to insert in the page beginning
095     */
096    public String getDirectEditIncludes(CmsDirectEditParams params) {
097
098        CmsMacroResolver resolver = prepareMacroResolverForIncludes(params);
099        return resolver.resolveMacros(m_headerInclude);
100    }
101
102    /**
103     * @see org.opencms.workplace.editors.directedit.A_CmsDirectEditProvider#init(org.opencms.file.CmsObject, org.opencms.workplace.editors.directedit.CmsDirectEditMode, java.lang.String)
104     */
105    @Override
106    public void init(CmsObject cms, CmsDirectEditMode mode, String fileName) {
107
108        super.init(cms, mode, fileName);
109
110        // check if the selected include file is available in the cache
111        CmsMemoryObjectCache cache = CmsMemoryObjectCache.getInstance();
112        m_headerInclude = (String)cache.getCachedObject(CmsDirectEditDefaultProvider.class, m_fileName);
113
114        if (m_headerInclude == null) {
115            // the file is not available in the cache
116            try {
117                CmsFile file = m_cms.readFile(m_fileName);
118                // create a String with the right encoding
119                m_headerInclude = getContentAsString(file);
120                // store this in the cache
121                cache.putCachedObject(CmsDirectEditDefaultProvider.class, m_fileName, m_headerInclude);
122
123            } catch (CmsException e) {
124                // this should better not happen
125                m_headerInclude = "";
126                LOG.error(Messages.get().getBundle().key(Messages.LOG_DIRECT_EDIT_NO_HEADER_1, fileName), e);
127            }
128        }
129    }
130
131    /**
132     * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditEnd(javax.servlet.jsp.PageContext)
133     */
134    public void insertDirectEditEnd(PageContext context) throws JspException {
135
136        String content;
137        switch (m_lastPermissionMode) {
138
139            case 1: // disabled
140                content = endDirectEditDisabled();
141                break;
142            case 2: // enabled
143                content = endDirectEditEnabled();
144                break;
145            default: // inactive or undefined
146                content = null;
147        }
148        m_lastPermissionMode = 0;
149        print(context, content);
150    }
151
152    /**
153     * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditIncludes(javax.servlet.jsp.PageContext, org.opencms.workplace.editors.directedit.CmsDirectEditParams)
154     */
155    public void insertDirectEditIncludes(PageContext context, CmsDirectEditParams params) throws JspException {
156
157        print(context, getDirectEditIncludes(params));
158    }
159
160    /**
161     * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#insertDirectEditStart(javax.servlet.jsp.PageContext, org.opencms.workplace.editors.directedit.CmsDirectEditParams)
162     */
163    public boolean insertDirectEditStart(PageContext context, CmsDirectEditParams params) throws JspException {
164
165        String content;
166        // check the direct edit permissions of the current user
167        CmsDirectEditResourceInfo resourceInfo = getResourceInfo(params, params.getResourceName());
168        // check the permission mode
169        m_lastPermissionMode = resourceInfo.getPermissions().getPermission();
170        switch (m_lastPermissionMode) {
171            case 1: // disabled
172                content = startDirectEditDisabled(params, resourceInfo);
173                break;
174            case 2: // enabled
175                content = startDirectEditEnabled(params, resourceInfo);
176                break;
177            default: // inactive or undefined
178                content = null;
179        }
180        print(context, content);
181        return content != null;
182    }
183
184    /**
185     * Returns <code>false</code> because the default provider does not support manual button placement.<p>
186     *
187     * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#isManual(org.opencms.workplace.editors.directedit.CmsDirectEditMode)
188     */
189    @Override
190    public boolean isManual(CmsDirectEditMode mode) {
191
192        return false;
193    }
194
195    /**
196     * @see org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider#newInstance()
197     */
198    public I_CmsDirectEditProvider newInstance() {
199
200        CmsDirectEditDefaultProvider result = new CmsDirectEditDefaultProvider();
201        result.m_configurationParameters = m_configurationParameters;
202        return result;
203    }
204
205    /**
206     * Returns the start HTML for a disabled direct edit button.<p>
207     *
208     * @param params the direct edit parameters
209     * @param resourceInfo contains information about the resource to edit
210     *
211     * @return the start HTML for a disabled direct edit button
212     */
213    public String startDirectEditDisabled(CmsDirectEditParams params, CmsDirectEditResourceInfo resourceInfo) {
214
215        String editId = getNextDirectEditId();
216        StringBuffer result = new StringBuffer(256);
217
218        result.append("<!-- EDIT BLOCK START (DISABLED): ");
219        result.append(params.m_resourceName);
220        result.append(" [");
221        result.append(resourceInfo.getResource().getState());
222        result.append("] ");
223        if (!resourceInfo.getLock().isUnlocked()) {
224            result.append(" locked ");
225            result.append(resourceInfo.getLock().getProject().getName());
226        }
227        result.append(" -->\n");
228
229        result.append("<script >\n");
230        result.append("registerButtonOcms(\"").append(editId).append("\");\n");
231        result.append("</script>\n");
232        result.append("<div class=\"ocms_de_bt\" id=\"buttons_").append(editId).append("\">\n");
233        result.append("<span onmouseover=\"activateOcms(\'").append(editId).append(
234            "\');\" onmouseout=\"deactivateOcms(\'").append(editId).append("\');\">\n");
235        result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" id=\"table_").append(editId).append(
236            "\"><tr>\n");
237        result.append("<td class=\"ocms_de\"><span class=\"ocms_disabled\">");
238        if (m_editButtonStyle == 1) {
239            result.append("<span class=\"ocms_combobutton\" style=\"background-image: url(\'").append(
240                CmsWorkplace.getSkinUri()).append("buttons/directedit_in.png\');\">&nbsp;").append(
241                    m_messages.key(Messages.GUI_EDITOR_FRONTEND_BUTTON_LOCKED_0)).append("</span>");
242        } else if (m_editButtonStyle == 2) {
243            result.append("<span class=\"ocms_combobutton\" style=\"padding-left: 4px;\">").append(
244                m_messages.key(Messages.GUI_EDITOR_FRONTEND_BUTTON_LOCKED_0)).append("</span>");
245        } else {
246            result.append("<img border=\"0\" src=\"").append(CmsWorkplace.getSkinUri()).append(
247                "buttons/directedit_in.png\" title=\"").append(
248                    m_messages.key(Messages.GUI_EDITOR_FRONTEND_BUTTON_LOCKED_0)).append("\" alt=\"\"/>");
249        }
250        result.append("</span></td>\n");
251        result.append("</tr></table>\n");
252        result.append("</span>\n");
253        result.append("</div>\n");
254        result.append("<div id=\"").append(editId).append("\" class=\"ocms_de_norm\">\n");
255
256        return result.toString();
257    }
258
259    /**
260     * Returns the start HTML for an enabled direct edit button.<p>
261     *
262     * @param params the direct edit parameters
263     * @param resourceInfo contains information about the resource to edit
264     *
265     * @return the start HTML for an enabled direct edit button
266     */
267    public String startDirectEditEnabled(CmsDirectEditParams params, CmsDirectEditResourceInfo resourceInfo) {
268
269        String editLocale = m_cms.getRequestContext().getLocale().toString();
270        String editId = getNextDirectEditId();
271        StringBuffer result = new StringBuffer(512);
272
273        String uri = m_cms.getRequestContext().getUri();
274
275        String editLink = getLink(params.getLinkForEdit());
276        String editNewLink = CmsEncoder.encode(params.getLinkForNew());
277
278        result.append("<!-- EDIT BLOCK START (ENABLED): ");
279        result.append(params.m_resourceName);
280        result.append(" [");
281        result.append(resourceInfo.getResource().getState());
282        result.append("]");
283        if (!resourceInfo.getLock().isUnlocked()) {
284            result.append(" locked ");
285            result.append(resourceInfo.getLock().getProject().getName());
286        }
287        result.append(" -->\n");
288
289        result.append("<script >\n");
290        result.append("registerButtonOcms(\"").append(editId).append("\");\n");
291        result.append("</script>\n");
292        result.append("<div class=\"ocms_de_bt\" id=\"buttons_").append(editId).append("\">\n");
293        result.append("<form name=\"form_").append(editId).append("\" id=\"form_").append(editId).append(
294            "\" method=\"post\" action=\"").append(editLink).append("\" class=\"ocms_nomargin\" target=\"_top\">\n");
295        result.append("<input type=\"hidden\" name=\"resource\" value=\"").append(params.getResourceName()).append(
296            "\"/>\n");
297        result.append("<input type=\"hidden\" name=\"directedit\" value=\"true\"/>\n");
298        result.append("<input type=\"hidden\" name=\"elementlanguage\" value=\"").append(editLocale).append("\"/>\n");
299        result.append("<input type=\"hidden\" name=\"elementname\" value=\"").append(params.getElement()).append(
300            "\"/>\n");
301        result.append("<input type=\"hidden\" name=\"backlink\" value=\"").append(uri).append("\"/>\n");
302        result.append("<input type=\"hidden\" name=\"newlink\"/>\n");
303        result.append("<input type=\"hidden\" name=\"closelink\"/>\n");
304        result.append("<input type=\"hidden\" name=\"redirect\" value=\"true\"/>\n");
305        result.append("<input type=\"hidden\" name=\"editortitle\"/>\n");
306        result.append("</form>\n");
307        result.append("<table onmouseover=\"activateOcms(\'").append(editId).append(
308            "\');\" onmouseout=\"deactivateOcms(\'").append(editId).append("\');\"");
309        result.append(" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" id=\"table_").append(editId).append(
310            "\"><tr>\n");
311        if (params.getButtonSelection().isShowEdit()) {
312            result.append("<td class=\"ocms_de\"><a href=\"#\" onclick=\"javascript:submitOcms(\'").append(
313                editId).append("\', \'").append(CmsDirectEditButtonSelection.VALUE_EDIT).append(
314                    "\');\" class=\"ocms_button\"><span class=\"ocms_over\" onmouseover=\"className=\'ocms_over\'\" onmouseout=\"className=\'ocms_over\'\" onmousedown=\"className=\'ocms_push\'\" onmouseup=\"className=\'ocms_over\'\">");
315            if (m_editButtonStyle == 1) {
316                result.append("<span id=\"bt_").append(editId).append(
317                    "\" class=\"ocms_combobutton\" style=\"background-image: url(\'").append(
318                        CmsWorkplace.getSkinUri()).append("buttons/directedit_cl.png\');\">&nbsp;").append(
319                            m_messages.key(Messages.GUI_EDITOR_FRONTEND_BUTTON_EDIT_0)).append("</span>");
320            } else if (m_editButtonStyle == 2) {
321                result.append("<span class=\"ocms_combobutton\" style=\"padding-left: 4px;\">").append(
322                    m_messages.key(Messages.GUI_EDITOR_FRONTEND_BUTTON_EDIT_0)).append("</span>");
323            } else {
324                result.append("<span id=\"bt_").append(editId).append(
325                    "\" class=\"ocms_combobutton\" style=\"padding-left: 15px; padding-right: 1px; background-image: url(\'").append(
326                        CmsWorkplace.getSkinUri()).append(
327                            "buttons/directedit_cl.png\'); background-position: 0px 0px;\" title=\"").append(
328                                m_messages.key(Messages.GUI_EDITOR_FRONTEND_BUTTON_EDIT_0)).append("\">&nbsp;</span>");
329            }
330            result.append("</span></a></td>\n");
331        }
332        if (params.getButtonSelection().isShowDelete()) {
333            result.append("<td class=\"ocms_de\"><a href=\"#\" onclick=\"javascript:submitOcms(\'").append(
334                editId).append("\', \'").append(CmsDirectEditButtonSelection.VALUE_DELETE).append(
335                    "\');\" class=\"ocms_button\"><span class=\"ocms_over\" onmouseover=\"className=\'ocms_over\'\" onmouseout=\"className=\'ocms_over\'\" onmousedown=\"className=\'ocms_push\'\" onmouseup=\"className=\'ocms_over\'\">");
336            if (m_editButtonStyle == 1) {
337                result.append("<span id=\"del_").append(editId).append(
338                    "\" class=\"ocms_combobutton\" style=\"background-image: url(\'").append(
339                        CmsWorkplace.getSkinUri()).append("buttons/deletecontent.png\');\">&nbsp;").append(
340                            m_messages.key(Messages.GUI_BUTTON_DELETE_0)).append("</span>");
341            } else if (m_editButtonStyle == 2) {
342                result.append("<span class=\"ocms_combobutton\" style=\"padding-left: 4px;\">").append(
343                    m_messages.key(Messages.GUI_BUTTON_DELETE_0)).append("</span>");
344            } else {
345                result.append("<img border=\"0\" src=\"").append(CmsWorkplace.getSkinUri()).append(
346                    "buttons/deletecontent.png\" title=\"").append(m_messages.key(Messages.GUI_BUTTON_DELETE_0)).append(
347                        "\" alt=\"\"/>");
348            }
349            result.append("</span></a></td>\n");
350        }
351        if (params.getButtonSelection().isShowNew()) {
352            result.append("<td class=\"ocms_de\"><a href=\"#\" onclick=\"javascript:submitOcms(\'").append(
353                editId).append("\', \'").append(CmsDirectEditButtonSelection.VALUE_NEW).append("\', \'").append(
354                    editNewLink).append(
355                        "\');\" class=\"ocms_button\"><span class=\"ocms_over\" onmouseover=\"className=\'ocms_over\'\" onmouseout=\"className=\'ocms_over\'\" onmousedown=\"className=\'ocms_push\'\" onmouseup=\"className=\'ocms_over\'\">");
356            if (m_editButtonStyle == 1) {
357                result.append("<span id=\"new_").append(editId).append(
358                    "\" class=\"ocms_combobutton\" style=\"background-image: url(\'").append(
359                        CmsWorkplace.getSkinUri()).append("buttons/new.png\');\">&nbsp;").append(
360                            m_messages.key(Messages.GUI_BUTTON_NEW_0)).append("</span>");
361            } else if (m_editButtonStyle == 2) {
362                result.append("<span class=\"ocms_combobutton\" style=\"padding-left: 4px;\">").append(
363                    m_messages.key(Messages.GUI_BUTTON_NEW_0)).append("</span>");
364            } else {
365                result.append("<img border=\"0\" src=\"").append(CmsWorkplace.getSkinUri()).append(
366                    "buttons/new.png\" title=\"").append(m_messages.key(Messages.GUI_BUTTON_NEW_0)).append(
367                        "\" alt=\"\"/>");
368            }
369            result.append("</span></a></td>");
370        }
371        result.append("</tr></table>\n");
372        result.append("</div>\n");
373        result.append("<div id=\"").append(editId).append("\" class=\"ocms_de_norm\">");
374        return result.toString();
375    }
376
377    /**
378     * Helper method to convert the content of a resource to a string.<p>
379     *
380     * @param file the file
381     * @return the file content as a string
382     *
383     * @throws CmsException if something goes wrong
384     */
385    protected String getContentAsString(CmsFile file) throws CmsException {
386
387        CmsProperty p = m_cms.readPropertyObject(file, CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING, true);
388        String e = p.getValue();
389        if (e == null) {
390            e = OpenCms.getSystemInfo().getDefaultEncoding();
391        }
392        return CmsEncoder.createString(file.getContents(), e);
393    }
394
395    /**
396     * Prepares the macro resolver which is used to process the included text file.<p>
397     *
398     * @param params the direct edit parameters
399     *
400     * @return the macro resolver
401     */
402    protected CmsMacroResolver prepareMacroResolverForIncludes(CmsDirectEditParams params) {
403
404        String closeLink = getLink(params.getLinkForClose());
405        String deleteLink = getLink(params.getLinkForDelete());
406        String titleForNew = m_messages.key(Messages.GUI_EDITOR_TITLE_NEW_0);
407        String skinUri = CmsWorkplace.getSkinUri();
408        // resolve macros in include header
409        CmsMacroResolver resolver = CmsMacroResolver.newInstance();
410        resolver.addMacro("closeLink", closeLink);
411        resolver.addMacro("deleteLink", deleteLink);
412        resolver.addMacro("titleForNew", titleForNew);
413        resolver.addMacro("skinUri", skinUri);
414        return resolver;
415    }
416}