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.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.containerpage.shared.CmsFormatterConfig; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.flex.CmsFlexController; 036import org.opencms.jsp.CmsJspTagContainer; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.main.OpenCms; 040import org.opencms.util.CmsUUID; 041import org.opencms.xml.containerpage.CmsContainerBean; 042import org.opencms.xml.containerpage.CmsContainerElementBean; 043import org.opencms.xml.containerpage.CmsContainerPageBean; 044import org.opencms.xml.containerpage.CmsFormatterConfiguration; 045import org.opencms.xml.containerpage.I_CmsFormatterBean; 046import org.opencms.xml.content.CmsXmlContentProperty; 047 048import java.util.HashMap; 049import java.util.HashSet; 050import java.util.List; 051import java.util.Locale; 052import java.util.Map; 053import java.util.Objects; 054import java.util.Set; 055 056import org.apache.commons.logging.Log; 057 058/** 059 * Wrapper for using container pages in JSPs. 060 */ 061public class CmsJspContainerPageWrapper { 062 063 /** Logger instance for this class. */ 064 private static final Log LOG = CmsLog.getLog(CmsJspContainerPageWrapper.class); 065 066 /** The wrapped container page bean. */ 067 private CmsContainerPageBean m_page; 068 069 /** The CMS context. */ 070 private CmsObject m_cms; 071 072 /** 073 * Creates a new instance. 074 * 075 * @param page the container page to wrap 076 */ 077 public CmsJspContainerPageWrapper(CmsObject cms, CmsContainerPageBean page) { 078 079 m_cms = cms; 080 m_page = page; 081 082 } 083 084 /** 085 * Checks if the page contains an element with a given id. 086 * 087 * @param elementId the element id to check 088 * @return true if the page contains the element 089 */ 090 public boolean containsElement(CmsUUID elementId) { 091 092 return m_page.containsElement(elementId); 093 } 094 095 /** 096 * Gets the containers. 097 * 098 * @return the containers 099 */ 100 public Map<String, CmsContainerBean> getContainers() { 101 102 return m_page.getContainers(); 103 } 104 105 /** 106 * Returns a map which tracks which element ids are part of the page. 107 * 108 * @return a map from element ids to their page membership 109 */ 110 public Map<CmsUUID, Boolean> getContainsElement() { 111 112 return m_page.getContainsElement(); 113 } 114 115 /** 116 * Gets the element ids. 117 * 118 * @return the container element ids 119 */ 120 public List<CmsUUID> getElementIds() { 121 122 return m_page.getElementIds(); 123 } 124 125 /** 126 * Gets the container elements 127 * @return the container elements 128 */ 129 public List<CmsContainerElementBean> getElements() { 130 131 return m_page.getElements(); 132 } 133 134 /** 135 * Gets the container names. 136 * 137 * @return the container names 138 */ 139 public List<String> getNames() { 140 141 return m_page.getNames(); 142 } 143 144 /** 145 * Gets the element settings for the element with the specific instance id. 146 * 147 * <p>The returned map contains the setting names as keys and the corresponding setting values as wrapper objects. 148 * 149 * @param elementInstanceId the element instance id 150 * @return the map of setting wrappers 151 */ 152 public Map<?, ?> getSettingsForElement(String elementInstanceId) { 153 154 for (CmsContainerBean container : m_page.getContainers().values()) { 155 for (CmsContainerElementBean element : container.getElements()) { 156 if (Objects.equals(element.getInstanceId(), elementInstanceId)) { 157 String containerName = container.getName(); 158 Map<String, String> settings = element.getSettings(); 159 I_CmsFormatterBean formatter = null; 160 CmsADEConfigData config = OpenCms.getADEManager().lookupConfigurationWithCache( 161 m_cms, 162 m_cms.getRequestContext().addSiteRoot(m_cms.getRequestContext().getUri())); 163 164 if (settings != null) { 165 String formatterConfigId = settings.get( 166 CmsFormatterConfig.getSettingsKeyForContainer(containerName)); 167 I_CmsFormatterBean dynamicFmt = config.findFormatter(formatterConfigId); 168 if (dynamicFmt != null) { 169 formatter = dynamicFmt; 170 } 171 } 172 if (formatter == null) { 173 try { 174 CmsResource resource = m_cms.readResource( 175 element.getId(), 176 CmsResourceFilter.ignoreExpirationOffline(m_cms)); 177 CmsFormatterConfiguration formatters = config.getFormatters(m_cms, resource); 178 int width = -2; 179 try { 180 width = Integer.parseInt(container.getWidth()); 181 } catch (Exception e) { 182 LOG.debug(e.getLocalizedMessage(), e); 183 } 184 formatter = formatters.getDefaultSchemaFormatter(container.getType(), width); 185 } catch (CmsException e1) { 186 if (LOG.isWarnEnabled()) { 187 LOG.warn(e1.getLocalizedMessage(), e1); 188 } 189 } catch (Exception e) { 190 LOG.error(e.getLocalizedMessage(), e); 191 } 192 } 193 194 final I_CmsFormatterBean finalFormatter = formatter; 195 196 Map<String, CmsXmlContentProperty> formatterSettingsConfig = OpenCms.getADEManager().getFormatterSettings( 197 m_cms, 198 config, 199 formatter, 200 element.getResource(), 201 m_cms.getRequestContext().getLocale(), 202 null); 203 Set<String> keys = new HashSet<>(element.getSettings().keySet()); 204 Map<String, CmsJspElementSettingValueWrapper> result = new HashMap<>(); 205 for (String key : keys) { 206 String value = element.getSettings().get(key); 207 boolean exists; 208 if (finalFormatter != null) { 209 exists = (formatterSettingsConfig.get(key) != null) 210 || finalFormatter.getSettings(config).containsKey(key); 211 } else { 212 exists = value != null; 213 } 214 result.put( 215 key, 216 new CmsJspElementSettingValueWrapper(m_cms, element.getSettings().get(key), exists)); 217 } 218 return result; 219 } 220 } 221 } 222 return CmsJspContentAccessBean.CONSTANT_NULL_VALUE_WRAPPER_MAP; 223 } 224 225 public Set<String> getTypes() { 226 227 return m_page.getTypes(); 228 } 229 230 /** 231 * Renders the element in the container with the given name or name prefix. 232 * @param context the context bean 233 * @param name the container name or name prefix 234 * @return the rendered HTML 235 */ 236 public String renderContainer(CmsJspStandardContextBean context, String name) { 237 238 CmsContainerBean container = findContainer(name); 239 if (container == null) { 240 return null; 241 } 242 return render(context, container); 243 } 244 245 /** 246 * Helper method for locating a container with the given name or name prefix. 247 * @param name the name or name prefix 248 * @return the container, or null if none were found 249 */ 250 private CmsContainerBean findContainer(String name) { 251 252 CmsContainerBean result = m_page.getContainers().get(name); 253 if (result == null) { 254 for (Map.Entry<String, CmsContainerBean> entry : m_page.getContainers().entrySet()) { 255 if (entry.getKey().endsWith("-" + name)) { 256 result = entry.getValue(); 257 break; 258 } 259 } 260 } 261 return result; 262 } 263 264 /** 265 * Renders the elements from the given container as HTML and returns it. 266 * 267 * @param context the context bean 268 * @param container the container whose elements should be rendered 269 * @return the HTML of the container elements, without a surrounding element 270 */ 271 private String render(CmsJspStandardContextBean context, CmsContainerBean container) { 272 273 CmsFlexController controller = CmsFlexController.getController(context.getRequest()); 274 CmsObject m_cms = context.getCmsObject(); 275 CmsContainerBean oldContainer = context.getContainer(); 276 CmsContainerElementBean oldElement = context.getRawElement(); 277 CmsContainerPageBean oldPage = context.getPage(); 278 boolean oldForceDisableEdit = context.isForceDisableEditMode(); 279 Locale locale = m_cms.getRequestContext().getLocale(); 280 context.getRequest(); 281 try { 282 context.setContainer(container); 283 context.setPage(m_page); 284 // The forceDisableEditMode flag may be incorrectly cached in the standard 285 // context bean copies stored in flex cache entries, but it doesn't matter since edit mode is never 286 // active in the Online project anyway 287 context.setForceDisableEditMode(true); 288 289 int containerWidth = -1; 290 try { 291 containerWidth = Integer.parseInt(container.getWidth()); 292 } catch (Exception e) { 293 LOG.debug(e.getLocalizedMessage(), e); 294 } 295 CmsADEConfigData adeConfig = context.getSitemapConfigInternal(); 296 StringBuilder buffer = new StringBuilder(); 297 for (CmsContainerElementBean element : container.getElements()) { 298 299 try { 300 element.initResource(m_cms); 301 I_CmsFormatterBean formatterBean = CmsJspTagContainer.ensureValidFormatterSettings( 302 m_cms, 303 element, 304 adeConfig, 305 container.getName(), 306 container.getType(), 307 containerWidth); 308 element.initSettings(m_cms, adeConfig, formatterBean, locale, controller.getCurrentRequest(), null); 309 context.setElement(element); 310 CmsResource formatterRes = m_cms.readResource( 311 formatterBean.getJspStructureId(), 312 CmsResourceFilter.IGNORE_EXPIRATION); 313 byte[] formatterOutput = OpenCms.getResourceManager().getLoader(formatterRes).dump( 314 m_cms, 315 formatterRes, 316 null, 317 locale, 318 controller.getCurrentRequest(), 319 controller.getCurrentResponse()); 320 String encoding = controller.getCurrentResponse().getEncoding(); 321 String formatterOutputStr = new String(formatterOutput, encoding); 322 buffer.append(formatterOutputStr); 323 } catch (Exception e) { 324 LOG.error(e.getLocalizedMessage(), e); 325 } 326 } 327 String resultHtml = buffer.toString(); 328 return resultHtml; 329 } finally { 330 context.setPage(oldPage); 331 context.setContainer(oldContainer); 332 context.setElement(oldElement); 333 context.setForceDisableEditMode(oldForceDisableEdit); 334 } 335 336 } 337 338}