/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software GmbH, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.workplace.editors; import org.opencms.file.CmsFile; import org.opencms.file.CmsObject; import org.opencms.file.CmsPropertyDefinition; import org.opencms.file.CmsResource; import org.opencms.file.CmsResourceFilter; import org.opencms.i18n.CmsEncoder; import org.opencms.i18n.CmsLocaleManager; import org.opencms.jsp.CmsJspActionElement; import org.opencms.lock.CmsLock; import org.opencms.lock.CmsLockType; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.OpenCms; import org.opencms.security.CmsPermissionSet; import org.opencms.security.I_CmsPrincipal; import org.opencms.util.CmsStringUtil; import org.opencms.workplace.CmsFrameset; import org.opencms.workplace.CmsWorkplace; import org.opencms.xml.content.CmsXmlContent; import org.opencms.xml.content.CmsXmlContentFactory; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import javax.servlet.ServletException; import javax.servlet.http.HttpSession; import javax.servlet.jsp.JspException; import org.apache.commons.logging.Log; /** * Provides basic methods for building the file editors of OpenCms.<p> * * The editor classes have to extend this class and implement action methods for common editor actions.<p> * * @since 6.0.0 */ public abstract class CmsEditor extends CmsEditorBase { /** Value for the action: change the body. */ public static final int ACTION_CHANGE_BODY = 124; /** Value for the action: delete the current locale. */ public static final int ACTION_DELETELOCALE = 140; /** Value for the action: exit. */ public static final int ACTION_EXIT = 122; /** Value for the action: show a preview. */ public static final int ACTION_PREVIEW = 126; /** Value for the action: save. */ public static final int ACTION_SAVE = 121; /** Constant value for the customizable action button. */ public static final int ACTION_SAVEACTION = 130; /** Value for the action: save and exit. */ public static final int ACTION_SAVEEXIT = 123; /** Value for the action: show the editor. */ public static final int ACTION_SHOW = 125; /** Value for the action: an error occurred. */ public static final int ACTION_SHOW_ERRORMESSAGE = 127; /** Value for the action parameter: change the element. */ public static final String EDITOR_CHANGE_ELEMENT = "changeelement"; /** Value for the action parameter: cleanup content. */ public static final String EDITOR_CLEANUP = "cleanup"; /** Value for the action parameter: close browser window (accidentally). */ public static final String EDITOR_CLOSEBROWSER = "closebrowser"; /** Value for the action parameter: delete the current locale. */ public static final String EDITOR_DELETELOCALE = "deletelocale"; /** Value for the action parameter: exit editor. */ public static final String EDITOR_EXIT = "exit"; /** Value for the action parameter: show a preview. */ public static final String EDITOR_PREVIEW = "preview"; /** Value for the action parameter: save content. */ public static final String EDITOR_SAVE = "save"; /** Value for the customizable action button. */ public static final String EDITOR_SAVEACTION = "saveaction"; /** Value for the action parameter: save and exit. */ public static final String EDITOR_SAVEEXIT = "saveexit"; /** Value for the action parameter: show the editor. */ public static final String EDITOR_SHOW = "show"; /** Value for the action parameter: an error occurred. */ public static final String EDITOR_SHOW_ERRORMESSAGE = "error"; /** Marker for empty locale in locale selection. */ public static final String EMPTY_LOCALE = " [-]"; /** Parameter name for the request parameter "backlink". */ public static final String PARAM_BACKLINK = "backlink"; /** Parameter name for the request parameter "content". */ public static final String PARAM_CONTENT = "content"; /** Parameter name for the request parameter "directedit". */ public static final String PARAM_DIRECTEDIT = "directedit"; /** Parameter name for the request parameter "editastext". */ public static final String PARAM_EDITASTEXT = "editastext"; /** Parameter name for the request parameter "editormode". */ public static final String PARAM_EDITORMODE = "editormode"; /** Parameter name for the request parameter "element language". */ public static final String PARAM_ELEMENTLANGUAGE = "elementlanguage"; /** Parameter name for the request parameter "loaddefault". */ public static final String PARAM_LOADDEFAULT = "loaddefault"; /** Parameter name for the request parameter "modified". */ public static final String PARAM_MODIFIED = "modified"; /** Parameter name for the request parameter "old element language". */ public static final String PARAM_OLDELEMENTLANGUAGE = "oldelementlanguage"; /** Parameter name for the request parameter "tempfile". */ public static final String PARAM_TEMPFILE = "tempfile"; /** Stores the VFS editor path. */ public static final String PATH_EDITORS = PATH_WORKPLACE + "editors/"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsEditor.class); /** A cloned cms instance that prevents the broken link remotion during unmarshalling. */ private CmsObject m_cloneCms; /** The editor session info bean. */ private CmsEditorSessionInfo m_editorSessionInfo; /** The encoding to use (will be read from the file property). */ private String m_fileEncoding; // some private members for parameter storage private String m_paramBackLink; private String m_paramContent; private String m_paramDirectedit; private String m_paramEditAsText; private String m_paramEditormode; private String m_paramElementlanguage; private String m_paramLoadDefault; private String m_paramModified; private String m_paramOldelementlanguage; private String m_paramTempFile; /** Helper variable to store the uri to the editors pictures. */ private String m_picsUri; /** * Public constructor.<p> * * @param jsp an initialized JSP action element */ public CmsEditor(CmsJspActionElement jsp) { super(jsp); } /** * Unlocks the edited resource when in direct edit mode or when the resource was not modified.<p> * * @param forceUnlock if true, the resource will be unlocked anyway */ public abstract void actionClear(boolean forceUnlock); /** * Performs the exit editor action.<p> * * @throws CmsException if something goes wrong * @throws IOException if a forward fails * @throws ServletException if a forward fails * @throws JspException if including an element fails */ public abstract void actionExit() throws CmsException, IOException, ServletException, JspException; /** * Performs the save content action.<p> * * @throws IOException if a redirection fails * @throws JspException if including an element fails */ public abstract void actionSave() throws IOException, JspException; /** * Builds the html String for the element language selector.<p> * * @param attributes optional attributes for the <select> tag * @param resourceName the name of the resource to edit * @param selectedLocale the currently selected Locale * @return the html for the element language selectbox */ public String buildSelectElementLanguage(String attributes, String resourceName, Locale selectedLocale) { // get locale names based on properties and global settings List locales = OpenCms.getLocaleManager().getAvailableLocales(getCms(), resourceName); List options = new ArrayList(locales.size()); List selectList = new ArrayList(locales.size()); int currentIndex = -1; //get the locales already used in the resource List contentLocales = new ArrayList(); try { CmsResource res = getCms().readResource(resourceName, CmsResourceFilter.IGNORE_EXPIRATION); String temporaryFilename = CmsWorkplace.getTemporaryFileName(resourceName); if (getCms().existsResource(temporaryFilename, CmsResourceFilter.IGNORE_EXPIRATION)) { res = getCms().readResource(temporaryFilename, CmsResourceFilter.IGNORE_EXPIRATION); } CmsFile file = getCms().readFile(res); CmsXmlContent xmlContent = CmsXmlContentFactory.unmarshal(getCms(), file); contentLocales = xmlContent.getLocales(); } catch (CmsException e) { // to nothing here in case the resource could not be opened if (LOG.isErrorEnabled()) { LOG.error(Messages.get().getBundle().key(Messages.LOG_GET_LOCALES_1, resourceName), e); } } for (int counter = 0; counter < locales.size(); counter++) { // create the list of options and values Locale curLocale = (Locale)locales.get(counter); selectList.add(curLocale.toString()); StringBuffer buf = new StringBuffer(); buf.append(curLocale.getDisplayName(getLocale())); if (!contentLocales.contains(curLocale)) { buf.append(EMPTY_LOCALE); } options.add(buf.toString()); if (curLocale.equals(selectedLocale)) { // set the selected index of the selector currentIndex = counter; } } if (currentIndex == -1) { // no matching element language found, use first element language in list if (selectList.size() > 0) { currentIndex = 0; setParamElementlanguage((String)selectList.get(0)); } } return buildSelect(attributes, options, selectList, currentIndex, false); } /** * Generates a button for the OpenCms editor.<p> * * @param href the href link for the button, if none is given the button will be disabled * @param target the href link target for the button, if none is given the target will be same window * @param image the image name for the button, skin path will be automatically added as prefix * @param label the label for the text of the button * @param type 0: image only (default), 1: image and text, 2: text only * @param useCustomImage if true, the button has to be placed in the editors "custom pics" folder * * @return a button for the OpenCms editor */ public String button(String href, String target, String image, String label, int type, boolean useCustomImage) { if (useCustomImage) { // search the picture in the "custom pics" folder return button(href, target, image, label, type, getPicsUri()); } else { // search the picture in the common "buttons" folder return button(href, target, image, label, type); } } /** * Returns the editor action for a "cancel" button.<p> * * This overwrites the cancel method of the CmsDialog class.<p> * * Always use this value, do not write anything directly in the html page.<p> * * @return the default action for a "cancel" button */ public String buttonActionCancel() { String target = null; if (Boolean.valueOf(getParamDirectedit()).booleanValue()) { // editor is in direct edit mode if (CmsStringUtil.isNotEmpty(getParamBacklink())) { // set link to the specified back link target target = getParamBacklink(); } else { // set link to the edited resource target = getParamResource(); } } else { // in workplace mode, show explorer view target = OpenCms.getLinkManager().substituteLink(getCms(), CmsFrameset.JSP_WORKPLACE_URI); } return "onclick=\"top.location.href='" + getJsp().link(target) + "';\""; } /** * Builds the html to display the special action button for the direct edit mode of the editor.<p> * * @param jsFunction the JavaScript function which will be executed on the mouseup event * @param type 0: image only (default), 1: image and text, 2: text only * @return the html to display the special action button */ public String buttonActionDirectEdit(String jsFunction, int type) { // get the action class from the OpenCms runtime property I_CmsEditorActionHandler actionClass = OpenCms.getWorkplaceManager().getEditorActionHandler(); String url; String name; boolean active = false; if (actionClass != null) { // get button parameters and state from action class url = actionClass.getButtonUrl(getJsp(), getParamResource()); name = actionClass.getButtonName(); active = actionClass.isButtonActive(getJsp(), getParamResource()); } else { // action class not defined, display inactive button url = getSkinUri() + "buttons/publish_in.png"; name = Messages.GUI_EXPLORER_CONTEXT_PUBLISH_0; } String image = url.substring(url.lastIndexOf("/") + 1); if (url.endsWith(".gif")) { image = image.substring(0, image.length() - 4); } if (active) { // create the link for the button return button( "javascript:" + jsFunction, null, image, name, type, url.substring(0, url.lastIndexOf("/") + 1)); } else { // create the inactive button return button(null, null, image, name, type, url.substring(0, url.lastIndexOf("/") + 1)); } } /** * @see org.opencms.workplace.CmsWorkplace#checkLock(String, CmsLockType) */ public void checkLock(String resource, CmsLockType type) throws CmsException { CmsResource res = getCms().readResource(resource, CmsResourceFilter.ALL); CmsLock lock = getCms().getLock(res); if (!lock.isNullLock()) { setParamModified(Boolean.TRUE.toString()); } // for resources with siblings make sure all sibling have at least a // temporary lock if ((res.getSiblingCount() > 1) && (lock.isInherited())) { super.checkLock(resource, CmsLockType.TEMPORARY); } else { super.checkLock(resource, type); } } /** * Generates a button for delete locale.<p> * * @param href the href link for the button, if none is given the button will be disabled * @param target the href link target for the button, if none is given the target will be same window * @param image the image name for the button, skin path will be automatically added as prefix * @param label the label for the text of the button * @param type 0: image only (default), 1: image and text, 2: text only * * @return a button for the OpenCms workplace */ public String deleteLocaleButton(String href, String target, String image, String label, int type) { String filename = getParamResource(); try { CmsResource res = getCms().readResource(filename, CmsResourceFilter.IGNORE_EXPIRATION); String temporaryFilename = CmsWorkplace.getTemporaryFileName(filename); if (getCms().existsResource(temporaryFilename, CmsResourceFilter.IGNORE_EXPIRATION)) { res = getCms().readResource(temporaryFilename, CmsResourceFilter.IGNORE_EXPIRATION); } CmsFile file = getCms().readFile(res); CmsXmlContent xmlContent = CmsXmlContentFactory.unmarshal(getCms(), file); int locales = xmlContent.getLocales().size(); // there are less than 2 locales, so disable the delete locale button if (locales < 2) { href = null; target = null; image += "_in"; } } catch (CmsException e) { // to nothing here in case the resource could not be opened if (LOG.isErrorEnabled()) { LOG.error(Messages.get().getBundle().key(Messages.LOG_GET_LOCALES_1, filename), e); } } return button(href, target, image, label, type, getSkinUri() + "buttons/"); } /** * Returns the instantiated editor display option class from the workplace manager.<p> * * This is a convenience method to be used on editor JSPs.<p> * * @return the instantiated editor display option class */ public CmsEditorDisplayOptions getEditorDisplayOptions() { return OpenCms.getWorkplaceManager().getEditorDisplayOptions(); } /** * Returns the URI to the editor resource folder where button images and javascripts are located.<p> * * @return the URI to the editor resource folder */ public abstract String getEditorResourceUri(); /** * Returns the OpenCms request context path.<p> * * This is a convenience method to use in the editor.<p> * * @return the OpenCms request context path */ public String getOpenCmsContext() { return OpenCms.getSystemInfo().getOpenCmsContext(); } /** * Returns the back link when closing the editor.<p> * * @return the back link */ public String getParamBacklink() { if ((m_editorSessionInfo != null) && CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_editorSessionInfo.getBackLink())) { m_paramBackLink = m_editorSessionInfo.getBackLink(); } if (m_paramBackLink == null) { m_paramBackLink = ""; } return m_paramBackLink; } /** * Returns the content of the editor.<p> * @return the content of the editor */ public String getParamContent() { if (m_paramContent == null) { m_paramContent = ""; } return m_paramContent; } /** * Returns the direct edit flag parameter.<p> * * @return the direct edit flag parameter */ public String getParamDirectedit() { if (m_editorSessionInfo != null) { return String.valueOf(m_editorSessionInfo.isDirectEdit()); } return m_paramDirectedit; } /** * Returns the edit as text parameter.<p> * * @return the edit as text parameter */ public String getParamEditastext() { return m_paramEditAsText; } /** * Returns the editor mode parameter.<p> * * @return the editor mode parameter */ public String getParamEditormode() { return m_paramEditormode; } /** * Returns the current element language.<p> * * @return the current element language */ public String getParamElementlanguage() { if (m_paramElementlanguage == null) { if ((m_editorSessionInfo != null) && (m_editorSessionInfo.getElementLocale() != null)) { m_paramElementlanguage = m_editorSessionInfo.getElementLocale().toString(); } } return m_paramElementlanguage; } /** * Returns the "loaddefault" parameter to determine if the default editor should be loaded.<p> * * @return the "loaddefault" parameter */ public String getParamLoaddefault() { return m_paramLoadDefault; } /** * Returns the modified parameter indicating if the resource has been saved.<p> * * @return the modified parameter indicating if the resource has been saved */ public String getParamModified() { return m_paramModified; } /** * Returns the old element language.<p> * * @return the old element language */ public String getParamOldelementlanguage() { return m_paramOldelementlanguage; } /** * Returns the name of the temporary file.<p> * * @return the name of the temporary file */ public String getParamTempfile() { return m_paramTempFile; } /** * Returns the path to the images used by this editor.<p> * * @return the path to the images used by this editor */ public String getPicsUri() { if (m_picsUri == null) { m_picsUri = getEditorResourceUri() + "pics/"; } return m_picsUri; } /** * Sets the back link when closing the editor.<p> * * @param backLink the back link */ public void setParamBacklink(String backLink) { m_paramBackLink = backLink; } /** * Sets the content of the editor.<p> * * @param content the content of the editor */ public void setParamContent(String content) { if (content == null) { content = ""; } m_paramContent = content; } /** * Sets the direct edit flag parameter.<p> * * @param direct the direct edit flag parameter */ public void setParamDirectedit(String direct) { m_paramDirectedit = direct; } /** * Sets the edit as text parameter.<p> * * @param editAsText <code>"true"</code> if the resource should be handled like a text file */ public void setParamEditastext(String editAsText) { m_paramEditAsText = editAsText; } /** * Sets the editor mode parameter.<p> * * @param mode the editor mode parameter */ public void setParamEditormode(String mode) { m_paramEditormode = mode; } /** * Sets the current element language.<p> * * @param elementLanguage the current element language */ public void setParamElementlanguage(String elementLanguage) { m_paramElementlanguage = elementLanguage; } /** * Sets the "loaddefault" parameter to determine if the default editor should be loaded.<p> * * @param loadDefault the "loaddefault" parameter */ public void setParamLoaddefault(String loadDefault) { m_paramLoadDefault = loadDefault; } /** * Sets the modified parameter indicating if the resource has been saved.<p> * * @param modified the modified parameter indicating if the resource has been saved */ public void setParamModified(String modified) { m_paramModified = modified; } /** * Sets the old element language.<p> * * @param oldElementLanguage the old element language */ public void setParamOldelementlanguage(String oldElementLanguage) { m_paramOldelementlanguage = oldElementLanguage; } /** * Sets the name of the temporary file.<p> * * @param fileName the name of the temporary file */ public void setParamTempfile(String fileName) { m_paramTempFile = fileName; } /** * Closes the editor and forwards to the workplace or the resource depending on the editor mode.<p> * * @throws IOException if forwarding fails * @throws ServletException if forwarding fails * @throws JspException if including a JSP fails */ protected void actionClose() throws IOException, JspException, ServletException { try { if (Boolean.valueOf(getParamDirectedit()).booleanValue()) { // editor is in direct edit mode if (CmsStringUtil.isNotEmpty(getParamBacklink())) { // set link to the specified back link target setParamCloseLink(getJsp().link(getParamBacklink())); } else { // set link to the edited resource setParamCloseLink(getJsp().link(getParamResource())); } // save initialized instance of this class in request attribute for included sub-elements getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); // load the common JSP close dialog getJsp().include(FILE_DIALOG_CLOSE); } else { if (CmsStringUtil.isNotEmpty(getParamBacklink())) { // set link to the specified back link target setParamCloseLink(getJsp().link(getParamBacklink())); // save initialized instance of this class in request attribute for included sub-elements getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); // load the common JSP close dialog getJsp().include(FILE_DIALOG_CLOSE); } else { // forward to the workplace explorer view sendForward(CmsFrameset.JSP_WORKPLACE_URI, new HashMap()); } } } finally { clearEditorSessionInfo(); } } /** * Clears the editor session info bean.<p> */ protected void clearEditorSessionInfo() { if (m_editorSessionInfo != null) { getSession().removeAttribute(m_editorSessionInfo.getEditorSessionInfoKey()); } m_editorSessionInfo = null; } /** * Writes the content of a temporary file back to the original file.<p> * * @throws CmsException if something goes wrong */ protected void commitTempFile() throws CmsException { CmsObject cms = getCms(); CmsFile tempFile; List properties; try { switchToTempProject(); tempFile = cms.readFile(getParamTempfile(), CmsResourceFilter.ALL); properties = cms.readPropertyObjects(getParamTempfile(), false); } finally { // make sure the project is reset in case of any exception switchToCurrentProject(); } if (cms.existsResource(getParamResource(), CmsResourceFilter.ALL)) { // update properties of original file first (required if change in encoding occurred) cms.writePropertyObjects(getParamResource(), properties); // now replace the content of the original file CmsFile orgFile = cms.readFile(getParamResource(), CmsResourceFilter.ALL); orgFile.setContents(tempFile.getContents()); getCloneCms().writeFile(orgFile); } else { // original file does not exist, remove visibility permission entries and copy temporary file // switch to the temporary file project cms.getRequestContext().setCurrentProject(cms.readProject(getSettings().getProject())); // lock the temporary file cms.changeLock(getParamTempfile()); // remove visibility permissions for everybody on temporary file if possible if (cms.hasPermissions(tempFile, CmsPermissionSet.ACCESS_CONTROL)) { cms.rmacc(getParamTempfile(), I_CmsPrincipal.PRINCIPAL_GROUP, OpenCms.getDefaultUsers().getGroupUsers()); cms.rmacc( getParamTempfile(), I_CmsPrincipal.PRINCIPAL_GROUP, OpenCms.getDefaultUsers().getGroupProjectmanagers()); } cms.copyResource(getParamTempfile(), getParamResource(), CmsResource.COPY_AS_NEW); // ensure the content handler is called CmsFile orgFile = cms.readFile(getParamResource(), CmsResourceFilter.ALL); getCloneCms().writeFile(orgFile); } // remove the temporary file flag int flags = cms.readResource(getParamResource(), CmsResourceFilter.ALL).getFlags(); if ((flags & CmsResource.FLAG_TEMPFILE) == CmsResource.FLAG_TEMPFILE) { flags ^= CmsResource.FLAG_TEMPFILE; cms.chflags(getParamResource(), flags); } } /** * Creates a temporary file which is needed while working in an editor with preview option.<p> * * @return the file name of the temporary file * @throws CmsException if something goes wrong */ protected String createTempFile() throws CmsException { return OpenCms.getWorkplaceManager().createTempFile(getCms(), getParamResource(), getSettings().getProject()); } /** * Decodes the given content the same way the client would do it.<p> * * Content is decoded as if it was encoded using the JavaScript * "encodeURIComponent()" function.<p> * * @param content the content to decode * @return the decoded content */ protected String decodeContent(String content) { return CmsEncoder.unescape(content, CmsEncoder.ENCODING_UTF_8); } /** * Decodes an individual parameter value, ensuring the content is always decoded in UTF-8.<p> * * For editors the content is always encoded using the * JavaScript encodeURIComponent() method on the client, * which always encodes in UTF-8.<p> * * @param paramName the name of the parameter * @param paramValue the unencoded value of the parameter * @return the encoded value of the parameter */ protected String decodeParamValue(String paramName, String paramValue) { if ((paramName != null) && (paramValue != null)) { if (PARAM_CONTENT.equals(paramName)) { // content will be always encoded in UTF-8 unicode by the editor client return CmsEncoder.decode(paramValue, CmsEncoder.ENCODING_UTF_8); } else if (PARAM_RESOURCE.equals(paramName) || PARAM_TEMPFILE.equals(paramName)) { String filename = CmsEncoder.decode(paramValue, getCms().getRequestContext().getEncoding()); if (PARAM_TEMPFILE.equals(paramName) || CmsStringUtil.isEmpty(getParamTempfile())) { // always use value from temp file if it is available setFileEncoding(getFileEncoding(getCms(), filename)); } return filename; } else { return CmsEncoder.decode(paramValue, getCms().getRequestContext().getEncoding()); } } else { return null; } } /** * Deletes a temporary file from the OpenCms VFS, needed when exiting an editor.<p> */ protected void deleteTempFile() { try { // switch to the temporary file project switchToTempProject(); // delete the temporary file getCms().deleteResource(getParamTempfile(), CmsResource.DELETE_PRESERVE_SIBLINGS); } catch (CmsException e) { // should usually never happen if (LOG.isInfoEnabled()) { LOG.info(e); } } finally { try { // switch back to the current project switchToCurrentProject(); } catch (CmsException e) { // should usually never happen if (LOG.isInfoEnabled()) { LOG.info(e); } } } } /** * Encodes the given content so that it can be transfered to the client.<p> * * Content is encoded so that it is compatible with the JavaScript * "decodeURIComponent()" function.<p> * * @param content the content to encode * @return the encoded content */ protected String encodeContent(String content) { return CmsEncoder.escapeWBlanks(content, CmsEncoder.ENCODING_UTF_8); } /** * Returns a cloned cms instance that prevents the time range resource filter check.<p> * * Use it always for unmarshalling and file writing.<p> * * @return a cloned cms instance that prevents the time range resource filter check * * @throws CmsException if something goes wrong */ protected CmsObject getCloneCms() throws CmsException { if (m_cloneCms == null) { m_cloneCms = OpenCms.initCmsObject(getCms()); m_cloneCms.getRequestContext().setRequestTime(CmsResource.DATE_RELEASED_EXPIRED_IGNORE); } return m_cloneCms; } /** * Returns the editor session info bean.<p> * * @return the editor session info bean */ protected CmsEditorSessionInfo getEditorSessionInfo() { return m_editorSessionInfo; } /** * Returns the encoding parameter.<p> * * @return the encoding parameter */ protected String getFileEncoding() { return m_fileEncoding; } /** * Helper method to determine the encoding of the given file in the VFS, * which must be set using the "content-encoding" property.<p> * * @param cms the CmsObject * @param filename the name of the file which is to be checked * @return the encoding for the file */ protected String getFileEncoding(CmsObject cms, String filename) { try { return cms.readPropertyObject(filename, CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING, true).getValue( OpenCms.getSystemInfo().getDefaultEncoding()); } catch (CmsException e) { return OpenCms.getSystemInfo().getDefaultEncoding(); } } /** * Initializes the editor content when openening the editor for the first time.<p> */ protected abstract void initContent(); /** * @see org.opencms.workplace.CmsWorkplace#initMessages() */ @Override protected void initMessages() { initSessionInfo(); super.initMessages(); } /** * Initializes the editor session info bean.<p> */ protected void initSessionInfo() { CmsResource editedResource = null; try { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(getParamResource())) { editedResource = getCms().readResource(getParamResource()); } } catch (CmsException e) { // ignore } CmsEditorSessionInfo info = null; if (editedResource != null) { HttpSession session = getSession(); info = (CmsEditorSessionInfo)session.getAttribute(CmsEditorSessionInfo.getEditorSessionInfoKey(editedResource)); if (info == null) { info = new CmsEditorSessionInfo(editedResource.getStructureId()); } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_paramBackLink)) { info.setBackLink(m_paramBackLink); } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_paramElementlanguage)) { info.setElementLocale(CmsLocaleManager.getLocale(m_paramElementlanguage)); } if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_paramDirectedit)) { info.setDirectEdit(Boolean.parseBoolean(m_paramDirectedit)); } session.setAttribute(info.getEditorSessionInfoKey(), info); } m_editorSessionInfo = info; } /** * Sets the encoding parameter.<p> * * @param value the encoding value to set */ protected void setFileEncoding(String value) { m_fileEncoding = CmsEncoder.lookupEncoding(value, value); } /** * Shows the selected error page in case of an exception.<p> * * @param exception the current exception * @throws JspException if inclusion of the error page fails */ protected void showErrorPage(Exception exception) throws JspException { // reset the action parameter setParamAction(""); showErrorPage(this, exception); // save not successful, set cancel action setAction(ACTION_CANCEL); return; } /** * Shows the selected error page in case of an exception.<p> * * @param editor initialized instance of the editor class * @param exception the current exception * @throws JspException if inclusion of the error page fails */ protected void showErrorPage(Object editor, Exception exception) throws JspException { // save initialized instance of the editor class in request attribute for included sub-elements getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, editor); // reading of file contents failed, show error dialog setAction(ACTION_SHOW_ERRORMESSAGE); setParamTitle(key(Messages.GUI_TITLE_EDIT_1, new Object[] {CmsResource.getName(getParamResource())})); if (exception != null) { getJsp().getRequest().setAttribute(ATTRIBUTE_THROWABLE, exception); if (CmsLog.getLog(editor).isWarnEnabled()) { CmsLog.getLog(editor).warn(exception.getLocalizedMessage(), exception); } } // include the common error dialog getJsp().include(FILE_DIALOG_SCREEN_ERRORPAGE); } }