001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.loader; 029 030import org.opencms.cache.CmsVfsMemoryObjectCache; 031import org.opencms.file.CmsFile; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsProperty; 034import org.opencms.file.CmsPropertyDefinition; 035import org.opencms.file.CmsResource; 036import org.opencms.json.JSONObject; 037import org.opencms.json.JSONTokener; 038import org.opencms.jsp.util.I_CmsJspDeviceSelector; 039import org.opencms.main.CmsException; 040import org.opencms.main.CmsLog; 041import org.opencms.main.OpenCms; 042import org.opencms.util.CmsMacroResolver; 043import org.opencms.util.CmsStringUtil; 044 045import java.util.ArrayList; 046import java.util.Collections; 047import java.util.HashMap; 048import java.util.LinkedHashMap; 049import java.util.List; 050import java.util.Map; 051 052import javax.servlet.http.HttpServletRequest; 053 054import org.apache.commons.logging.Log; 055 056/** 057 * Example implementation of a template context provider for deciding between a desktop template and a mobile template.<p> 058 * 059 * The template JSP paths are read from a VFS file "/system/config/templatecontexts.json" 060 * 061 */ 062public class CmsDefaultTemplateContextProvider implements I_CmsTemplateContextProvider { 063 064 /** JSON attribute name. */ 065 public static final String A_HEIGHT = "height"; 066 067 /** JSON attribute name. */ 068 public static final String A_NICE_NAME = "niceName"; 069 070 /** JSON attribute name. */ 071 public static final String A_PATH = "path"; 072 073 /** JSON attribute name. */ 074 public static final String A_VARIANTS = "variants"; 075 076 /** JSON attribute name. */ 077 public static final String A_WIDTH = "width"; 078 079 /** The name for the configuration parameter which points to the template contexts configuration file. */ 080 public static final String PARAM_CONFIGURATION = "configuration"; 081 082 /** The logger instance for this class. */ 083 private static final Log LOG = CmsLog.getLog(CmsDefaultTemplateContextProvider.class); 084 085 /** Cache for the template contexts. */ 086 private CmsVfsMemoryObjectCache m_cache = new CmsVfsMemoryObjectCache(); 087 088 /** The stored Cms context. */ 089 private CmsObject m_cms; 090 091 /** Map of configuration parameters for the provider instance. */ 092 private Map<String, String> m_params; 093 094 /** Default constructor. */ 095 public CmsDefaultTemplateContextProvider() { 096 097 } 098 099 /** 100 * @see org.opencms.loader.I_CmsTemplateContextProvider#getAllContexts() 101 */ 102 public synchronized Map<String, CmsTemplateContext> getAllContexts() { 103 104 return Collections.unmodifiableMap(getContextMap()); 105 } 106 107 /** 108 * Returns the absolute VFS path where the configuration property file is stored.<p> 109 * 110 * 111 * @return the absolute VFS path where the configuration property file is stored 112 */ 113 public String getConfigurationPropertyPath() { 114 115 if (m_params.containsKey(PARAM_CONFIGURATION)) { 116 return m_params.get(PARAM_CONFIGURATION); 117 } else { 118 return OpenCms.getSystemInfo().getConfigFilePath(m_cms, "templatecontexts.json"); 119 } 120 } 121 122 /** 123 * @see org.opencms.loader.I_CmsTemplateContextProvider#getEditorStyleSheet(org.opencms.file.CmsObject, java.lang.String) 124 */ 125 public String getEditorStyleSheet(CmsObject cms, String editedResourcePath) { 126 127 String templatePath = getAllContexts().get("desktop").getTemplatePath(); 128 String result = null; 129 try { 130 CmsProperty property = cms.readPropertyObject(templatePath, CmsPropertyDefinition.PROPERTY_TEMPLATE, true); 131 if (!property.isNullProperty()) { 132 result = property.getValue(); 133 } 134 } catch (CmsException e) { 135 LOG.error(e.getLocalizedMessage(), e); 136 } 137 return result; 138 } 139 140 /** 141 * @see org.opencms.loader.I_CmsTemplateContextProvider#getOverrideCookieName() 142 */ 143 public String getOverrideCookieName() { 144 145 return "templatecontext"; 146 } 147 148 /** 149 * @see org.opencms.loader.I_CmsTemplateContextProvider#getTemplateContext(org.opencms.file.CmsObject, javax.servlet.http.HttpServletRequest, org.opencms.file.CmsResource) 150 */ 151 public synchronized CmsTemplateContext getTemplateContext( 152 CmsObject cms, 153 HttpServletRequest request, 154 CmsResource resource) { 155 156 I_CmsJspDeviceSelector selector = OpenCms.getSystemInfo().getDeviceSelector(); 157 String deviceType = request != null ? selector.getDeviceType(request) : null; 158 Map<String, CmsTemplateContext> contextMap = getAllContexts(); 159 if ((deviceType != null) && contextMap.containsKey(deviceType)) { 160 return contextMap.get(deviceType); 161 } else { 162 return contextMap.get("desktop"); 163 } 164 } 165 166 /** 167 * @see org.opencms.loader.I_CmsTemplateContextProvider#initialize(org.opencms.file.CmsObject, java.lang.String) 168 */ 169 public void initialize(CmsObject cms, String config) { 170 171 m_cms = cms; 172 if (CmsStringUtil.isEmptyOrWhitespaceOnly(config)) { 173 m_params = new HashMap<String, String>(); 174 } else { 175 m_params = CmsStringUtil.splitAsMap(config, ",", "="); 176 177 } 178 getAllContexts(); 179 } 180 181 /** 182 * @see org.opencms.loader.I_CmsTemplateContextProvider#readCommonProperty(org.opencms.file.CmsObject, java.lang.String, java.lang.String) 183 */ 184 public String readCommonProperty(CmsObject cms, String propertyName, String fallbackValue) throws CmsException { 185 186 String templatePath = getAllContexts().get("desktop").getTemplatePath(); 187 return cms.readPropertyObject(templatePath, propertyName, false).getValue(fallbackValue); 188 } 189 190 /** 191 * Gets the context map, either from a cache or from the VFS if it'S not already cached.<p> 192 * 193 * @return the context map 194 */ 195 @SuppressWarnings("unchecked") 196 private Map<String, CmsTemplateContext> getContextMap() { 197 198 Object cachedObj = m_cache.getCachedObject(m_cms, getConfigurationPropertyPath()); 199 if (cachedObj != null) { 200 return (Map<String, CmsTemplateContext>)cachedObj; 201 } else { 202 try { 203 Map<String, CmsTemplateContext> map = initMap(); 204 m_cache.putCachedObject(m_cms, getConfigurationPropertyPath(), map); 205 return map; 206 } catch (Exception e) { 207 LOG.error(e.getLocalizedMessage(), e); 208 return Collections.emptyMap(); 209 } 210 } 211 212 } 213 214 /** 215 * Loads the context map from the VFS.<p> 216 * 217 * @return the context map 218 * @throws Exception if something goes wrong 219 */ 220 private Map<String, CmsTemplateContext> initMap() throws Exception { 221 222 Map<String, CmsTemplateContext> result = new LinkedHashMap<String, CmsTemplateContext>(); 223 String path = getConfigurationPropertyPath(); 224 CmsResource resource = m_cms.readResource(path); 225 CmsFile file = m_cms.readFile(resource); 226 String fileContent = new String(file.getContents(), "UTF-8"); 227 CmsMacroResolver resolver = new CmsMacroResolver(); 228 resolver.setCmsObject(m_cms); 229 for (Map.Entry<String, String> param : m_params.entrySet()) { 230 resolver.addMacro(param.getKey(), param.getValue()); 231 } 232 fileContent = resolver.resolveMacros(fileContent); 233 JSONTokener tok = new JSONTokener(fileContent); 234 tok.setOrdered(true); 235 JSONObject root = new JSONObject(tok, true); 236 for (String templateContextName : root.keySet()) { 237 JSONObject templateContextJson = (JSONObject)(root.opt(templateContextName)); 238 CmsJsonMessageContainer jsonMessage = new CmsJsonMessageContainer(templateContextJson.opt(A_NICE_NAME)); 239 String templatePath = (String)templateContextJson.opt(A_PATH); 240 JSONObject variantsJson = (JSONObject)templateContextJson.opt(A_VARIANTS); 241 List<CmsClientVariant> variants = new ArrayList<CmsClientVariant>(); 242 if (variantsJson != null) { 243 for (String variantName : variantsJson.keySet()) { 244 JSONObject variantJson = (JSONObject)variantsJson.opt(variantName); 245 CmsJsonMessageContainer variantMessage = new CmsJsonMessageContainer(variantJson.opt(A_NICE_NAME)); 246 int width = variantJson.optInt(A_WIDTH, 800); 247 int height = variantJson.optInt(A_HEIGHT, 600); 248 CmsClientVariant variant = new CmsClientVariant( 249 variantName, 250 variantMessage, 251 width, 252 height, 253 new HashMap<String, String>()); 254 variants.add(variant); 255 } 256 } 257 CmsTemplateContext templateContext = new CmsTemplateContext( 258 templateContextName, 259 templatePath, 260 jsonMessage, 261 this, 262 variants, 263 false); 264 result.put(templateContextName, templateContext); 265 266 } 267 return result; 268 } 269}