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.editors; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.jsp.CmsJspActionElement; 034import org.opencms.jsp.CmsJspNavBuilder; 035import org.opencms.jsp.CmsJspNavElement; 036import org.opencms.main.CmsException; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.util.CmsCollectionsGenericWrapper; 040 041import java.io.ByteArrayInputStream; 042import java.io.IOException; 043import java.io.InputStream; 044import java.util.List; 045import java.util.Map; 046import java.util.Properties; 047 048import org.apache.commons.logging.Log; 049 050/** 051 * Provides methods to determine the display options of a workplace editor for the current user.<p> 052 * 053 * On the editor JSP, do the following: 054 * <ul> 055 * <li>get the object instance with <code>OpenCms.getWorkplaceManager().getEditorDisplayOptions()</code>.</li> 056 * <li>get the Properties for the current user with <code>getDisplayOptions(CmsJspActionElement)</code>.</li> 057 * <li>use <code>showElement(key, Properties)</code> to determine if an element is shown.</li> 058 * </ul> 059 * 060 * Define your editor display options in property files located in the VFS folder 061 * <code>/system/config/wysiwyg/</code>.<p> 062 * 063 * Set navigation position property values on the configuration files 064 * and use the permission system to determine which groups and users 065 * should use which configuration file.<p> 066 * 067 * The configuration with the most enabled options should be the first in navigation, 068 * followed by configurations with less enabled options, because 069 * the first file readable for the current user will be used for configuration.<p> 070 * 071 * If no configuration file can be found for the current user, 072 * all display options will be disabled by default.<p> 073 * 074 * @since 6.0.0 075 */ 076public class CmsEditorDisplayOptions { 077 078 /** The name of the configuration folder.<p> */ 079 public static final String FOLDER_EDITORCONFIGURATION = "wysiwyg/"; 080 081 /** Mapping entry name that is used if no mapping is available for the user.<p> */ 082 public static final String NO_MAPPING_FOR_USER = "na"; 083 084 /** Maximum size of the stored editor configurations.<p> */ 085 public static final int SIZE_CONFIGURATIONFILES = 12; 086 087 /** Maximum size of the user editor configuration mappings.<p> */ 088 public static final int SIZE_USERENTRIES = 100; 089 090 /** The log object for this class. */ 091 private static final Log LOG = CmsLog.getLog(CmsEditorDisplayOptions.class); 092 093 /** Stores all loaded editor configuration options.<p> */ 094 private Map<Object, Object> m_loadedConfigurations; 095 096 /** Stores the mappings of users to their configuration options to use.<p> */ 097 private Map<Object, Object> m_userMappings; 098 099 /** 100 * Constructor that initializes the editor display options for the workplace.<p> 101 */ 102 public CmsEditorDisplayOptions() { 103 104 // initialize members 105 m_userMappings = CmsCollectionsGenericWrapper.createLRUMap(SIZE_USERENTRIES); 106 m_loadedConfigurations = CmsCollectionsGenericWrapper.createLRUMap(SIZE_CONFIGURATIONFILES); 107 } 108 109 /** 110 * Clears the cached user configuration data, casing a reload off all configurations.<p> 111 */ 112 public synchronized void clearCache() { 113 114 m_userMappings.clear(); 115 m_loadedConfigurations.clear(); 116 } 117 118 /** 119 * Reads the editor configuration file valid for the current user and caches the result in a Map.<p> 120 * 121 * The configuration settings of the found file are stored in a Map holding the loaded configuration 122 * with the configuration file name as key.<p> 123 * 124 * The configuration file name to use for the current user is stored in another Map with the user name 125 * as key.<p> 126 * 127 * @param jsp the JSP action element to access the VFS and current user information 128 * @return the display options to use for the current user or null if no display options were found 129 */ 130 public Properties getDisplayOptions(CmsJspActionElement jsp) { 131 132 return getDisplayOptions(jsp.getCmsObject()); 133 } 134 135 /** 136 * Reads the editor configuration file valid for the current user and caches the result in a Map.<p> 137 * 138 * The configuration settings of the found file are stored in a Map holding the loaded configuration 139 * with the configuration file name as key.<p> 140 * 141 * The configuration file name to use for the current user is stored in another Map with the user name 142 * as key.<p> 143 * 144 * @param cms the CmsObject to access the VFS and current user information 145 * @return the display options to use for the current user or null if no display options were found 146 */ 147 public Properties getDisplayOptions(CmsObject cms) { 148 149 // get the configuration file name for the current user 150 String mappedConfigFile = (String)m_userMappings.get(cms.getRequestContext().getCurrentUser().getName()); 151 Properties displayOptions; 152 if (mappedConfigFile == null) { 153 // no configuration file name stored for user, get the navigation items of the configuration folder 154 String configFolder = OpenCms.getSystemInfo().getConfigFilePath(cms, FOLDER_EDITORCONFIGURATION); 155 List<CmsJspNavElement> items = new CmsJspNavBuilder(cms).getNavigationForFolder(configFolder); 156 if (items.size() > 0) { 157 // get first found configuration file 158 CmsJspNavElement nav = items.get(0); 159 mappedConfigFile = nav.getFileName(); 160 synchronized (m_loadedConfigurations) { 161 // must sync read/write access to shared map 162 displayOptions = (Properties)m_loadedConfigurations.get(nav.getFileName()); 163 if (displayOptions == null) { 164 // configuration file has not yet been loaded, load it 165 try { 166 // read configuration file 167 CmsFile optionFile = cms.readFile( 168 nav.getResourceName(), 169 CmsResourceFilter.IGNORE_EXPIRATION); 170 InputStream in = new ByteArrayInputStream(optionFile.getContents()); 171 displayOptions = new Properties(); 172 displayOptions.load(in); 173 // store loaded options 174 m_loadedConfigurations.put(nav.getFileName(), displayOptions); 175 } catch (CmsException e) { 176 // set configuration to not available 177 if (LOG.isInfoEnabled()) { 178 LOG.info(e.getLocalizedMessage(), e); 179 } 180 mappedConfigFile = NO_MAPPING_FOR_USER; 181 } catch (IOException e) { 182 // set configuration to not available 183 if (LOG.isInfoEnabled()) { 184 LOG.info(e.getLocalizedMessage(), e); 185 } 186 mappedConfigFile = NO_MAPPING_FOR_USER; 187 displayOptions = null; 188 } 189 } 190 } 191 } else { 192 // no configuration available for current user, store this in mapping 193 mappedConfigFile = NO_MAPPING_FOR_USER; 194 displayOptions = null; 195 } 196 if (LOG.isDebugEnabled()) { 197 // check which mapping has been stored 198 LOG.debug( 199 Messages.get().getBundle().key( 200 Messages.LOG_MAP_CONFIG_FILE_TO_USER_2, 201 mappedConfigFile, 202 cms.getRequestContext().getCurrentUser().getName())); 203 } 204 // store the file name of the configuration file for the current user 205 m_userMappings.put(cms.getRequestContext().getCurrentUser().getName(), mappedConfigFile); 206 } else { 207 // configuration file for current user is known, get options from loaded configurations 208 displayOptions = (Properties)m_loadedConfigurations.get(mappedConfigFile); 209 } 210 // return the editor display options for this user 211 return displayOptions; 212 } 213 214 /** 215 * Returns the value for the given key from the display options.<p> 216 * 217 * @param key he element key name which should be read 218 * @param defaultValue the default value to use in case the property is not found 219 * @param displayOptions the display options for the current user 220 * 221 * @return the value for the given key from the display options 222 */ 223 public String getOptionValue(String key, String defaultValue, Properties displayOptions) { 224 225 if (displayOptions == null) { 226 return defaultValue; 227 } 228 return displayOptions.getProperty(key, defaultValue); 229 } 230 231 /** 232 * Determines if the given element should be shown in the editor.<p> 233 * 234 * @param key the element key name which should be displayed 235 * @param displayOptions the display options for the current user 236 * 237 * @return true if the element should be shown, otherwise false 238 */ 239 public boolean showElement(String key, Properties displayOptions) { 240 241 return showElement(key, null, displayOptions); 242 } 243 244 /** 245 * Determines if the given element should be shown in the editor.<p> 246 * 247 * @param key the element key name which should be displayed 248 * @param defaultValue the default value to use in case the property is not found, should be a boolean value as String 249 * @param displayOptions the display options for the current user 250 * 251 * @return true if the element should be shown, otherwise false 252 */ 253 public boolean showElement(String key, String defaultValue, Properties displayOptions) { 254 255 if (defaultValue == null) { 256 return ((displayOptions != null) && Boolean.valueOf(displayOptions.getProperty(key)).booleanValue()); 257 } 258 if (displayOptions == null) { 259 return Boolean.valueOf(defaultValue).booleanValue(); 260 } 261 return Boolean.valueOf(displayOptions.getProperty(key, defaultValue)).booleanValue(); 262 } 263}