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.jsp.util; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsResource; 034import org.opencms.file.history.I_CmsHistoryResource; 035import org.opencms.main.CmsException; 036import org.opencms.main.CmsRuntimeException; 037import org.opencms.util.CmsCollectionsGenericWrapper; 038 039import java.util.Map; 040 041import org.apache.commons.collections.Transformer; 042 043/** 044 * Allows access to the attributes and properties of a resource, usually used inside a loop of a 045 * <code><cms:resourceload></code> tag.<p> 046 * 047 * The implementation is optimized for performance and uses lazy initializing of the 048 * requested values as much as possible.<p> 049 * 050 * @since 8.0 051 * 052 * @see org.opencms.jsp.CmsJspTagResourceAccess 053 */ 054public class CmsJspResourceAccessBean { 055 056 /** 057 * Transformer that reads a history resource property, 058 * the input is used as String for the history property name to read.<p> 059 */ 060 private class CmsHistoryPropertyLoaderTransformer implements Transformer { 061 062 /** The resource where the properties are read from. */ 063 private I_CmsHistoryResource m_res; 064 065 /** 066 * Creates a new property loading Transformer.<p> 067 * 068 * @param resource the resource where the properties are read from 069 */ 070 public CmsHistoryPropertyLoaderTransformer(CmsResource resource) { 071 072 m_res = (I_CmsHistoryResource)resource; 073 074 } 075 076 /** 077 * @see org.apache.commons.collections.Transformer#transform(java.lang.Object) 078 */ 079 public Object transform(Object input) { 080 081 String result; 082 try { 083 // read the requested history property 084 result = CmsProperty.get( 085 String.valueOf(input), 086 getCmsObject().readHistoryPropertyObjects(m_res)).getValue(); 087 } catch (@SuppressWarnings("unused") CmsException e) { 088 // unable to read history property, return null 089 result = null; 090 } 091 return result; 092 } 093 } 094 095 /** The OpenCms context of the current user. */ 096 private CmsObject m_cms; 097 098 /** The file that can be accessed. */ 099 private CmsFile m_file; 100 101 /** The history properties of the resource. */ 102 private Map<String, String> m_historyProperties; 103 104 /** The properties of the resource. */ 105 private Map<String, String> m_properties; 106 107 /** 108 * The properties of the resource according to the provided locale. 109 * The map goes from locale -> property -> value. 110 */ 111 private Map<String, Map<String, String>> m_localeProperties; 112 113 /** The resource that can be accessed. */ 114 private CmsResource m_resource; 115 116 /** 117 * No argument constructor, required for a JavaBean.<p> 118 * 119 * You must call {@link #init(CmsObject, CmsResource)} and provide the 120 * required values when you use this constructor.<p> 121 * 122 * @see #init(CmsObject, CmsResource) 123 */ 124 public CmsJspResourceAccessBean() { 125 126 // must call init() manually later 127 } 128 129 /** 130 * Creates a content access bean based on a Resource.<p> 131 * 132 * @param cms the OpenCms context of the current user 133 * @param resource the resource to create the content from 134 */ 135 public CmsJspResourceAccessBean(CmsObject cms, CmsResource resource) { 136 137 init(cms, resource); 138 } 139 140 /** 141 * Returns the OpenCms user context this bean was initialized with.<p> 142 * 143 * @return the OpenCms user context this bean was initialized with 144 */ 145 public CmsObject getCmsObject() { 146 147 return m_cms; 148 } 149 150 /** 151 * Returns the raw VFS file object of the current resource.<p> 152 * 153 * This can be used to access information from the raw file on a JSP.<p> 154 * 155 * Usage example on a JSP with the JSTL:<pre> 156 * <cms:resourceload ... > 157 * <cms:resourceaccess var="res" /> 158 * Root path of the resource: ${res.file.rootPath} 159 * </cms:resourceload></pre> 160 * 161 * @return the raw VFS file object the content accessed by this bean was created from 162 */ 163 public CmsFile getFile() { 164 165 if (m_file == null) { 166 try { 167 m_file = m_cms.readFile(m_resource); 168 } catch (CmsException e) { 169 // this usually should not happen, as the resource already has been read by the current user 170 // and we just upgrade it to a file 171 throw new CmsRuntimeException( 172 Messages.get().container(Messages.ERR_FILE_READ_1, m_resource.getRootPath()), 173 e); 174 } 175 } 176 return m_file; 177 } 178 179 /** 180 * Returns the file contents of the raw VFS file object as String.<p> 181 * 182 * Usage example on a JSP with the JSTL:<pre> 183 * <cms:resourceload ... > 184 * <cms:resourceaccess var="res" /> 185 * String content of the resource: ${res.fileContentAsString} 186 * </cms:resourceload></pre> 187 * 188 * @return the file contents of the raw VFS file object as String 189 */ 190 public String getFileContentAsString() { 191 192 return new String(getFile().getContents()); 193 } 194 195 /** 196 * Returns the site path of the current resource, that is the result of 197 * {@link CmsObject#getSitePath(CmsResource)} with the resource 198 * obtained by {@link #getFile()}.<p> 199 * 200 * Usage example on a JSP with the JSTL:<pre> 201 * &<cms:resourceload ... > 202 * <cms:resourceaccess var="res" /> 203 * Site path of the resource: "${res.filename}"; 204 * </cms:resourceload></pre> 205 * 206 * @return the site path of the current resource 207 * 208 * @see CmsObject#getSitePath(CmsResource) 209 */ 210 public String getFilename() { 211 212 return m_cms.getSitePath(m_resource); 213 } 214 215 /** 216 * Short form for {@link #getReadHistoryProperties()}.<p> 217 * 218 * This works only if the current resource is implementing {@link I_CmsHistoryResource}.<p> 219 * 220 * Usage example on a JSP with the <code><cms:resourceaccess></code> tag:<pre> 221 * <cms:resourceload ... > 222 * <cms:resourceaccess var="res" /> 223 * History "Title" property value of the resource: ${res.historyProperty['Title']} 224 * </cms:resourceload></pre> 225 * 226 * @return a map that lazily reads history properties of the resource 227 * 228 * @see #getReadHistoryProperties() 229 */ 230 public Map<String, String> getHistoryProperty() { 231 232 return getReadHistoryProperties(); 233 } 234 235 /** 236 * Short form for {@link #getReadProperties()}.<p> 237 * 238 * Usage example on a JSP with the <code><cms:resourceaccess></code> tag:<pre> 239 * <cms:resourceload ... > 240 * <cms:resourceaccess var="res" /> 241 * "Title" property value of the resource: ${res.property['Title']} 242 * </cms:resourceload></pre> 243 * 244 * @return a map that lazily reads properties of the resource 245 * 246 * @see #getReadProperties() 247 */ 248 public Map<String, String> getProperty() { 249 250 return getReadProperties(); 251 } 252 253 /** 254 * Short form for {@link #getReadPropertiesLocale()}.<p> 255 * 256 * Usage example on a JSP with the <code><cms:resourceaccess></code> tag:<pre> 257 * <cms:resourceload ... > 258 * <cms:resourceaccess var="res" /> 259 * "Title" property value of the resource: ${res.property['de']['Title']} 260 * </cms:resourceload></pre> 261 * 262 * @return a map that lazily reads properties of the resource and accesses them wrt. to the specified locale. 263 * 264 * @see #getReadPropertiesLocale() 265 */ 266 public Map<String, Map<String, String>> getPropertyLocale() { 267 268 return getReadPropertiesLocale(); 269 } 270 271 /** 272 * Returns a map that lazily reads history properties of the resource.<p> 273 * 274 * This works only if the current resource is implementing {@link I_CmsHistoryResource}.<p> 275 * 276 * Usage example on a JSP with the <code><cms:resourceaccess></code> tag:<pre> 277 * <cms:resourceload ... > 278 * <cms:resourceaccess var="res" /> 279 * History "Title" property value of the resource: ${res.readHistoryProperties['Title']} 280 * </cms:resourceload></pre> 281 * 282 * @return a map that lazily reads properties of the resource 283 * 284 * @see #getProperty() for a short form of this method 285 */ 286 public Map<String, String> getReadHistoryProperties() { 287 288 if (m_historyProperties == null) { 289 // create lazy map only on demand 290 m_historyProperties = CmsCollectionsGenericWrapper.createLazyMap( 291 new CmsHistoryPropertyLoaderTransformer(m_resource)); 292 } 293 return m_historyProperties; 294 } 295 296 /** 297 * Returns a map that lazily reads properties of the resource.<p> 298 * 299 * Usage example on a JSP with the <code><cms:resourceaccess></code> tag:<pre> 300 * <cms:resourceload ... > 301 * <cms:resourceaccess var="res" /> 302 * "Title" property value of the resource: ${res.readProperties['Title']} 303 * </cms:resourceload></pre> 304 * 305 * @return a map that lazily reads properties of the resource 306 * 307 * @see #getProperty() for a short form of this method 308 */ 309 public Map<String, String> getReadProperties() { 310 311 if (m_properties == null) { 312 // create lazy map only on demand 313 m_properties = CmsCollectionsGenericWrapper.createLazyMap( 314 new CmsJspValueTransformers.CmsPropertyLoaderTransformer(m_cms, m_resource, false)); 315 } 316 return m_properties; 317 } 318 319 /** 320 * Returns a map that lazily reads properties of the resource and makes the accessible according to the specified locale.<p> 321 * 322 * Usage example on a JSP with the <code><cms:resourceaccess></code> tag:<pre> 323 * <cms:resourceload ... > 324 * <cms:resourceaccess var="res" /> 325 * "Title" property value of the resource: ${res.readProperties['de']['Title']} 326 * </cms:resourceload></pre> 327 * 328 * @return a map that lazily reads properties of the resource and makes the accessible according to the specified locale. 329 * 330 * @see #getPropertyLocale() for a short form of this method 331 */ 332 public Map<String, Map<String, String>> getReadPropertiesLocale() { 333 334 if (m_localeProperties == null) { 335 m_localeProperties = CmsCollectionsGenericWrapper.createLazyMap( 336 new CmsJspValueTransformers.CmsLocalePropertyLoaderTransformer(m_cms, m_resource, false)); 337 } 338 return m_localeProperties; 339 340 } 341 342 /** 343 * Returns the current resource.<p> 344 * 345 * Usage example on a JSP with the JSTL:<pre> 346 * &<cms:resourceload ... > 347 * <cms:resourceaccess var="res" /> 348 * Root path of the resource: "${res.resource.rootPath}"; 349 * </cms:resourceload></pre> 350 * 351 * @return the current resource 352 */ 353 public CmsResource getResource() { 354 355 return m_resource; 356 } 357 358 /** 359 * Returns an instance of a VFS access bean, 360 * initialized with the OpenCms user context this bean was created with.<p> 361 * 362 * @return an instance of a VFS access bean, 363 * initialized with the OpenCms user context this bean was created with 364 */ 365 public CmsJspVfsAccessBean getVfs() { 366 367 return CmsJspVfsAccessBean.create(m_cms); 368 } 369 370 /** 371 * Initialize this instance.<p> 372 * 373 * @param cms the OpenCms context of the current user 374 * @param resource the resource to create the content from 375 */ 376 public void init(CmsObject cms, CmsResource resource) { 377 378 m_cms = cms; 379 m_resource = resource; 380 } 381}