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; 029 030import org.opencms.ade.configuration.CmsADEConfigData; 031import org.opencms.ade.containerpage.shared.CmsContainerElement; 032import org.opencms.ade.containerpage.shared.CmsFormatterConfig; 033import org.opencms.file.CmsObject; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.file.collectors.I_CmsCollectorPostCreateHandler; 037import org.opencms.flex.CmsFlexController; 038import org.opencms.jsp.util.CmsJspContentAccessValueWrapper; 039import org.opencms.jsp.util.CmsJspStandardContextBean; 040import org.opencms.main.CmsException; 041import org.opencms.main.CmsLog; 042import org.opencms.main.OpenCms; 043import org.opencms.util.CmsRequestUtil; 044import org.opencms.util.CmsUUID; 045import org.opencms.workplace.editors.directedit.CmsAdvancedDirectEditProvider; 046import org.opencms.workplace.editors.directedit.CmsDirectEditMode; 047import org.opencms.workplace.editors.directedit.I_CmsDirectEditProvider; 048import org.opencms.xml.containerpage.CmsADESessionCache; 049import org.opencms.xml.containerpage.CmsContainerElementBean; 050import org.opencms.xml.containerpage.CmsFormatterConfiguration; 051import org.opencms.xml.containerpage.I_CmsFormatterBean; 052import org.opencms.xml.types.CmsXmlDisplayFormatterValue; 053import org.opencms.xml.types.I_CmsXmlContentValue; 054 055import java.util.HashMap; 056import java.util.LinkedHashMap; 057import java.util.List; 058import java.util.Locale; 059import java.util.Map; 060import java.util.Map.Entry; 061 062import javax.servlet.ServletRequest; 063import javax.servlet.ServletResponse; 064import javax.servlet.http.HttpServletRequest; 065import javax.servlet.jsp.PageContext; 066import javax.servlet.jsp.tagext.BodyTagSupport; 067 068import org.apache.commons.logging.Log; 069 070/** 071 * The 'display' tag can be used to display a single resource using a formatter. It also allows to activate direct editing.<p> 072 */ 073public class CmsJspTagDisplay extends BodyTagSupport implements I_CmsJspTagParamParent { 074 075 /** The log object for this class. */ 076 private static final Log LOG = CmsLog.getLog(CmsJspTagDisplay.class); 077 078 /** The serial version id. */ 079 private static final long serialVersionUID = 2285680951218629093L; 080 081 /** Flag, indicating if the create option should be displayed. */ 082 private boolean m_canCreate; 083 084 /** Flag, indicating if the delete option should be displayed. */ 085 private boolean m_canDelete; 086 087 /** The tag attribute's value, specifying the path to the (sub)sitemap where new content should be created. */ 088 private String m_creationSiteMap; 089 090 /** The display formatter ids. */ 091 private Map<String, CmsUUID> m_displayFormatterIds; 092 093 /** The display formatter paths. */ 094 private Map<String, String> m_displayFormatterPaths; 095 096 /** The editable flag. */ 097 private boolean m_editable; 098 099 /** The settings parameter map. */ 100 private Map<String, String> m_parameterMap; 101 102 /** The pass settings flag. */ 103 private boolean m_passSettings; 104 105 /** The fully qualified class name of the post create handler to use. */ 106 private String m_postCreateHandler; 107 108 /** The element settings to be used. */ 109 private Map<String, String> m_settings; 110 111 /** The site path to the resource to display. */ 112 private String m_value; 113 114 /** 115 * Constructor.<p> 116 */ 117 public CmsJspTagDisplay() { 118 119 m_parameterMap = new LinkedHashMap<String, String>(); 120 m_displayFormatterPaths = new HashMap<String, String>(); 121 m_displayFormatterIds = new HashMap<String, CmsUUID>(); 122 } 123 124 /** 125 * Includes the formatter rendering the given element.<p> 126 * 127 * @param element the element 128 * @param formatter the formatter configuration bean 129 * @param editable if editable 130 * @param canCreate if new resources may be created 131 * @param canDelete if the resource may be deleted 132 * @param creationSiteMap the create location sub site 133 * @param postCreateHandler the post create handler 134 * @param context the page context 135 * @param request the request 136 * @param response the response 137 */ 138 public static void displayAction( 139 CmsContainerElementBean element, 140 I_CmsFormatterBean formatter, 141 boolean editable, 142 boolean canCreate, 143 boolean canDelete, 144 String creationSiteMap, 145 String postCreateHandler, 146 PageContext context, 147 ServletRequest request, 148 ServletResponse response) { 149 150 if (CmsFlexController.isCmsRequest(request)) { 151 // this will always be true if the page is called through OpenCms 152 CmsObject cms = CmsFlexController.getCmsObject(request); 153 Locale locale = cms.getRequestContext().getLocale(); 154 boolean isOnline = cms.getRequestContext().getCurrentProject().isOnlineProject(); 155 CmsJspStandardContextBean contextBean = CmsJspStandardContextBean.getInstance(request); 156 CmsContainerElementBean parentElement = contextBean.getElement(); 157 158 try { 159 if (formatter != null) { 160 element.initResource(cms); 161 element.initSettings(cms, formatter, locale, request, null); 162 boolean openedEditable = false; 163 contextBean.setElement(element); 164 if (editable && contextBean.getIsEditMode()) { 165 if (CmsJspTagEditable.getDirectEditProvider(context) == null) { 166 I_CmsDirectEditProvider eb = new CmsAdvancedDirectEditProvider(); 167 eb.init(cms, CmsDirectEditMode.TRUE, element.getSitePath()); 168 request.setAttribute(I_CmsDirectEditProvider.ATTRIBUTE_DIRECT_EDIT_PROVIDER, eb); 169 } 170 171 openedEditable = CmsJspTagEdit.insertDirectEditStart( 172 cms, 173 context, 174 element.getResource(), 175 canCreate, 176 canDelete, 177 null, 178 creationSiteMap, 179 postCreateHandler); 180 CmsADESessionCache.getCache( 181 (HttpServletRequest)(context.getRequest()), 182 cms).setCacheContainerElement(element.editorHash(), element); 183 } 184 try { 185 CmsJspTagInclude.includeTagAction( 186 context, 187 cms.getRequestContext().removeSiteRoot(formatter.getJspRootPath()), 188 null, 189 locale, 190 false, 191 isOnline, 192 CmsRequestUtil.createParameterMap(element.getSettings()), 193 CmsRequestUtil.getAtrributeMap(request), 194 request, 195 response); 196 } catch (Exception e) { 197 LOG.error(e.getLocalizedMessage(), e); 198 } 199 if (openedEditable) { 200 CmsJspTagEdit.insertDirectEditEnd(context); 201 } 202 } 203 } catch (CmsException e) { 204 LOG.error(e.getLocalizedMessage(), e); 205 } 206 contextBean.setElement(parentElement); 207 } 208 209 } 210 211 /** 212 * Includes the formatter rendering the given element.<p> 213 * 214 * @param element the element 215 * @param formatter the formatter configuration bean 216 * @param context the page context 217 * @param request the request 218 * @param response the response 219 */ 220 public static void displayAction( 221 CmsContainerElementBean element, 222 I_CmsFormatterBean formatter, 223 PageContext context, 224 ServletRequest request, 225 ServletResponse response) { 226 227 displayAction(element, formatter, false, false, false, null, null, context, request, response); 228 } 229 230 /** 231 * Includes the formatter rendering the given element.<p> 232 * 233 * @param elementResource the element resource 234 * @param formatter the formatter configuration bean 235 * @param settings the element settings 236 * @param editable if editable 237 * @param canCreate if new resources may be created 238 * @param canDelete if the resource may be deleted 239 * @param creationSiteMap the create location sub site 240 * @param postCreateHandler the post create handler 241 * @param context the page context 242 * @param request the request 243 * @param response the response 244 */ 245 public static void displayAction( 246 CmsResource elementResource, 247 I_CmsFormatterBean formatter, 248 Map<String, String> settings, 249 boolean editable, 250 boolean canCreate, 251 boolean canDelete, 252 String creationSiteMap, 253 String postCreateHandler, 254 PageContext context, 255 ServletRequest request, 256 ServletResponse response) { 257 258 CmsContainerElementBean element = new CmsContainerElementBean( 259 elementResource.getStructureId(), 260 formatter.getJspStructureId(), 261 settings, 262 false); 263 displayAction( 264 element, 265 formatter, 266 editable, 267 canCreate, 268 canDelete, 269 creationSiteMap, 270 postCreateHandler, 271 context, 272 request, 273 response); 274 } 275 276 /** 277 * Adds a display formatter.<p> 278 * 279 * @param type the resource type 280 * @param path the path to the formatter configuration file.<p> 281 */ 282 public void addDisplayFormatter(String type, String path) { 283 284 m_displayFormatterPaths.put(type, path); 285 } 286 287 /** 288 * @see org.opencms.jsp.I_CmsJspTagParamParent#addParameter(java.lang.String, java.lang.String) 289 */ 290 public void addParameter(String name, String value) { 291 292 // No null values allowed in parameters 293 if ((name == null) || (value == null)) { 294 return; 295 } 296 297 m_parameterMap.put(name, value); 298 } 299 300 /** 301 * @see javax.servlet.jsp.tagext.BodyTagSupport#doEndTag() 302 */ 303 @Override 304 public int doEndTag() { 305 306 ServletRequest request = pageContext.getRequest(); 307 ServletResponse response = pageContext.getResponse(); 308 if (CmsFlexController.isCmsRequest(request)) { 309 // this will always be true if the page is called through OpenCms 310 CmsObject cms = CmsFlexController.getCmsObject(request); 311 try { 312 boolean isOnline = cms.getRequestContext().getCurrentProject().isOnlineProject(); 313 CmsResource res = null; 314 if (CmsUUID.isValidUUID(m_value)) { 315 CmsUUID structureId = new CmsUUID(m_value); 316 res = isOnline 317 ? cms.readResource(structureId) 318 : cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION); 319 } else { 320 res = isOnline 321 ? cms.readResource(m_value) 322 : cms.readResource(m_value, CmsResourceFilter.IGNORE_EXPIRATION); 323 } 324 I_CmsFormatterBean formatter = getFormatterForType(cms, res, isOnline); 325 Map<String, String> settings = new HashMap<String, String>(); 326 String formatterId = formatter.getId(); 327 int prefixLength = formatterId.length() + 1; 328 for (Entry<String, String> entry : m_parameterMap.entrySet()) { 329 if (CmsContainerElement.ELEMENT_INSTANCE_ID.equals(entry.getKey())) { 330 // remove any instance id to make sure to generate a unique one 331 continue; 332 } 333 if (entry.getKey().startsWith(CmsFormatterConfig.FORMATTER_SETTINGS_KEY)) { 334 settings.put(entry.getKey(), formatter.getId()); 335 } else if (entry.getKey().startsWith(formatterId)) { 336 settings.put(entry.getKey().substring(prefixLength), entry.getValue()); 337 } else if (!settings.containsKey(entry.getKey())) { 338 settings.put(entry.getKey(), entry.getValue()); 339 } 340 } 341 342 displayAction( 343 res, 344 formatter, 345 settings, 346 m_editable, 347 m_canCreate, 348 m_canDelete, 349 m_creationSiteMap, 350 m_postCreateHandler, 351 pageContext, 352 request, 353 response); 354 } catch (CmsException e) { 355 LOG.error(e.getLocalizedMessage(), e); 356 } 357 } 358 release(); 359 return EVAL_PAGE; 360 } 361 362 /** 363 * @see javax.servlet.jsp.tagext.BodyTagSupport#doStartTag() 364 */ 365 @Override 366 public int doStartTag() { 367 368 if (Boolean.valueOf(m_passSettings).booleanValue()) { 369 CmsContainerElementBean element = CmsJspStandardContextBean.getInstance( 370 pageContext.getRequest()).getElement(); 371 if (element != null) { 372 m_parameterMap.putAll(element.getSettings()); 373 } 374 } 375 if (m_settings != null) { 376 m_parameterMap.putAll(m_settings); 377 } 378 379 return EVAL_BODY_BUFFERED; 380 } 381 382 /** 383 * Returns the editable.<p> 384 * 385 * @return the editable 386 */ 387 public boolean getEditable() { 388 389 return m_editable; 390 } 391 392 /** 393 * Returns the passSettings.<p> 394 * 395 * @return the passSettings 396 */ 397 public boolean getPassSettings() { 398 399 return m_passSettings; 400 } 401 402 /** 403 * Returns the element settings to be used.<p> 404 * 405 * @return the element settings to be used 406 */ 407 public Map<String, String> getSettings() { 408 409 return m_settings; 410 } 411 412 /** 413 * Returns the value.<p> 414 * 415 * @return the value 416 */ 417 public String getValue() { 418 419 return m_value; 420 } 421 422 /** 423 * @see javax.servlet.jsp.tagext.BodyTagSupport#release() 424 */ 425 @Override 426 public void release() { 427 428 super.release(); 429 m_parameterMap.clear(); 430 m_displayFormatterPaths.clear(); 431 m_displayFormatterIds.clear(); 432 m_settings = null; 433 m_passSettings = false; 434 m_editable = false; 435 m_value = null; 436 } 437 438 /** Setter for the "create" attribute of the tag. 439 * @param canCreate value of the tag's attribute "create". 440 */ 441 public void setCreate(boolean canCreate) { 442 443 m_canCreate = canCreate; 444 } 445 446 /** Setter for the "create" attribute of the tag. 447 * @param canCreate value of the tag's attribute "create". 448 */ 449 public void setCreate(String canCreate) { 450 451 m_canCreate = Boolean.valueOf(canCreate).booleanValue(); 452 } 453 454 /** Setter for the "creationSiteMap" attribute of the tag. 455 * @param sitePath value of the "creationSiteMap" attribute of the tag. 456 */ 457 public void setCreationSiteMap(String sitePath) { 458 459 m_creationSiteMap = sitePath; 460 } 461 462 /**Setter for the "delete" attribute of the tag. 463 * @param canDelete value of the "delete" attribute of the tag. 464 */ 465 public void setDelete(boolean canDelete) { 466 467 m_canDelete = canDelete; 468 } 469 470 /**Setter for the "delete" attribute of the tag. 471 * @param canDelete value of the "delete" attribute of the tag. 472 */ 473 public void setDelete(String canDelete) { 474 475 m_canDelete = Boolean.valueOf(canDelete).booleanValue(); 476 } 477 478 /** 479 * Sets the items.<p> 480 * 481 * @param displayFormatters the items to set 482 */ 483 public void setDisplayFormatters(Object displayFormatters) { 484 485 if (displayFormatters instanceof List) { 486 for (Object formatterItem : ((List<?>)displayFormatters)) { 487 if (formatterItem instanceof CmsJspContentAccessValueWrapper) { 488 addFormatter((CmsJspContentAccessValueWrapper)formatterItem); 489 } 490 } 491 } else if (displayFormatters instanceof CmsJspContentAccessValueWrapper) { 492 addFormatter((CmsJspContentAccessValueWrapper)displayFormatters); 493 } else if (displayFormatters instanceof String) { 494 String[] temp = ((String)displayFormatters).split(CmsXmlDisplayFormatterValue.SEPARATOR); 495 if (temp.length == 2) { 496 addDisplayFormatter(temp[0], temp[1]); 497 } 498 } 499 } 500 501 /** 502 * Sets the editable.<p> 503 * 504 * @param editable the editable to set 505 */ 506 public void setEditable(boolean editable) { 507 508 m_editable = editable; 509 } 510 511 /** 512 * Sets the editable.<p> 513 * 514 * @param editable the editable to set 515 */ 516 public void setEditable(String editable) { 517 518 m_editable = Boolean.valueOf(editable).booleanValue(); 519 } 520 521 /** 522 * Sets the passSettings.<p> 523 * 524 * @param passSettings the passSettings to set 525 */ 526 public void setPassSettings(Boolean passSettings) { 527 528 m_passSettings = passSettings.booleanValue(); 529 } 530 531 /** Setter for the "postCreateHandler" attribute of the tag. 532 * @param postCreateHandler fully qualified class name of the {@link I_CmsCollectorPostCreateHandler} to use. 533 */ 534 public void setPostCreateHandler(final String postCreateHandler) { 535 536 m_postCreateHandler = postCreateHandler; 537 } 538 539 /** 540 * Sets the element settings to be used.<p> 541 * 542 * @param settings the element settings to be used 543 */ 544 public void setSettings(Map<String, String> settings) { 545 546 m_settings = settings; 547 } 548 549 /** 550 * Sets the value.<p> 551 * 552 * @param value the value to set 553 */ 554 public void setValue(String value) { 555 556 m_value = value; 557 } 558 559 /** 560 * Adds a formatter.<p> 561 * 562 * @param formatterItem the formatter value 563 */ 564 private void addFormatter(CmsJspContentAccessValueWrapper formatterItem) { 565 566 I_CmsXmlContentValue val = formatterItem.getContentValue(); 567 if (val instanceof CmsXmlDisplayFormatterValue) { 568 CmsXmlDisplayFormatterValue value = (CmsXmlDisplayFormatterValue)val; 569 String type = value.getDisplayType(); 570 CmsUUID formatterId = value.getFormatterId(); 571 if (formatterId != null) { 572 m_displayFormatterIds.put(type, formatterId); 573 } 574 } 575 } 576 577 /** 578 * Returns the config for the requested resource, or <code>null</code> if not available.<p> 579 * 580 * @param cms the cms context 581 * @param resource the resource 582 * @param isOnline the is online flag 583 * 584 * @return the formatter configuration bean 585 */ 586 private I_CmsFormatterBean getFormatterForType(CmsObject cms, CmsResource resource, boolean isOnline) { 587 588 String typeName = OpenCms.getResourceManager().getResourceType(resource).getTypeName(); 589 I_CmsFormatterBean result = null; 590 if (m_displayFormatterPaths.containsKey(typeName)) { 591 try { 592 CmsResource res = cms.readResource(m_displayFormatterPaths.get(typeName)); 593 result = OpenCms.getADEManager().getCachedFormatters(isOnline).getFormatters().get( 594 res.getStructureId()); 595 } catch (CmsException e) { 596 LOG.error(e.getLocalizedMessage(), e); 597 } 598 } else if (m_displayFormatterIds.containsKey(typeName)) { 599 result = OpenCms.getADEManager().getCachedFormatters(isOnline).getFormatters().get( 600 m_displayFormatterIds.get(typeName)); 601 } else { 602 CmsADEConfigData config = OpenCms.getADEManager().lookupConfiguration( 603 cms, 604 cms.addSiteRoot(cms.getRequestContext().getFolderUri())); 605 if (config != null) { 606 CmsFormatterConfiguration formatters = config.getFormatters(cms, resource); 607 if (formatters != null) { 608 result = formatters.getDisplayFormatter(); 609 } 610 } 611 } 612 return result; 613 } 614}