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.commons; 029 030import org.opencms.configuration.CmsParameterConfiguration; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsPropertyDefinition; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.file.types.CmsResourceTypeXmlPage; 037import org.opencms.i18n.CmsEncoder; 038import org.opencms.jsp.CmsJspActionElement; 039import org.opencms.lock.CmsLock; 040import org.opencms.lock.CmsLockFilter; 041import org.opencms.main.CmsException; 042import org.opencms.main.CmsLog; 043import org.opencms.main.OpenCms; 044import org.opencms.security.CmsPermissionSet; 045import org.opencms.util.CmsStringUtil; 046import org.opencms.workplace.CmsDialogSelector; 047import org.opencms.workplace.CmsTabDialog; 048import org.opencms.workplace.CmsWorkplace; 049import org.opencms.workplace.CmsWorkplaceSettings; 050import org.opencms.workplace.I_CmsDialogHandler; 051import org.opencms.workplace.I_CmsPostUploadDialogHandler; 052import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 053 054import java.util.ArrayList; 055import java.util.Collections; 056import java.util.HashMap; 057import java.util.Iterator; 058import java.util.List; 059import java.util.Map; 060import java.util.RandomAccess; 061 062import javax.servlet.http.HttpServletRequest; 063import javax.servlet.http.HttpServletResponse; 064import javax.servlet.jsp.JspException; 065import javax.servlet.jsp.PageContext; 066 067import org.apache.commons.logging.Log; 068 069/** 070 * Provides methods for the properties dialog.<p> 071 * 072 * The following files use this class: 073 * <ul> 074 * <li>/commons/property_advanced.jsp 075 * </ul> 076 * <p> 077 * 078 * @since 6.0.0 079 */ 080public class CmsPropertyAdvanced extends CmsTabDialog implements I_CmsDialogHandler, I_CmsPostUploadDialogHandler { 081 082 /** Value for the action: save defined property. */ 083 public static final int ACTION_SAVE_DEFINE = 400; 084 085 /** Value for the action: save edited properties. */ 086 public static final int ACTION_SAVE_EDIT = 300; 087 088 /** Value for the action: show define property form. */ 089 public static final int ACTION_SHOW_DEFINE = 200; 090 091 /** Value for the action: show edit properties form. */ 092 public static final int ACTION_SHOW_EDIT = 100; 093 094 /** Constant for the "Define" button in the build button method. */ 095 public static final int BUTTON_DEFINE = 201; 096 097 /** Constant for the "Finish" button in the build button method. */ 098 public static final int BUTTON_FINISH = 202; 099 100 /** Request parameter value for the action: save defined property. */ 101 public static final String DIALOG_SAVE_DEFINE = "savedefine"; 102 103 /** Request parameter value for the action: save edited properties. */ 104 public static final String DIALOG_SAVE_EDIT = "saveedit"; 105 106 /** Request parameter value for the action: show information form. */ 107 public static final String DIALOG_SHOW_DEFAULT = "default"; 108 109 /** Request parameter value for the action: show define property form. */ 110 public static final String DIALOG_SHOW_DEFINE = "define"; 111 112 /** Request parameter value for the action: show edit properties form. */ 113 public static final String DIALOG_SHOW_EDIT = "edit"; 114 115 /** The dialog type. */ 116 public static final String DIALOG_TYPE = "property"; 117 118 /** Value for the dialog mode: new resource wizard. */ 119 public static final String MODE_WIZARD = "wizard"; 120 121 /** Value for the dialog mode: new resource wizard with creation of index page for new folder. */ 122 public static final String MODE_WIZARD_CREATEINDEX = "wizardcreateindex"; 123 124 /** Value for the dialog mode: new resource wizard with index page created in new folder. */ 125 public static final String MODE_WIZARD_INDEXCREATED = "wizardindexcreated"; 126 127 /** Key name for the resource panel. */ 128 public static final String PANEL_RESOURCE = "panel.properties.resource"; 129 130 /** Key name for the structure panel. */ 131 public static final String PANEL_STRUCTURE = "panel.properties.structure"; 132 133 /** Request parameter name for the new property definition. */ 134 public static final String PARAM_DIALOGMODE = "dialogmode"; 135 136 /** Configuration key for the dialog handler flag. */ 137 public static final String PARAM_HIDEADVANCED = "hideadvanced"; 138 139 /** Request parameter name for the new property definition. */ 140 public static final String PARAM_NEWPROPERTY = "newproperty"; 141 142 /** Configuration key for the upload handler class. */ 143 public static final String PARAM_POSTUPLOADHANDLER = "upload-handler"; 144 145 /** Configuration key for the group name. */ 146 public static final String PARAM_SHOWGROUP = "showgroup"; 147 148 /** Prefix for the hidden fields. */ 149 public static final String PREFIX_HIDDEN = "valhidden"; 150 151 /** Prefix for the hidden resource value. */ 152 public static final String PREFIX_RESOURCE = "valresource"; 153 154 /** Prefix for the hidden structure value. */ 155 public static final String PREFIX_STRUCTURE = "valstructure"; 156 157 /** Prefix for the use property checkboxes. */ 158 public static final String PREFIX_USEPROPERTY = "useprop"; 159 160 /** Prefix for the input values. */ 161 public static final String PREFIX_VALUE = "valprop"; 162 163 /** Name for the shared (resource) property tab. */ 164 public static final String TAB_RESOURCE = "tabres"; 165 166 /** Name for the individual (structure) property tab. */ 167 public static final String TAB_STRUCTURE = "tabstr"; 168 169 /** The URI to the customized property dialog. */ 170 public static final String URI_PROPERTY_CUSTOM_DIALOG = PATH_DIALOGS + "property_custom.jsp"; 171 172 /** The URI to the standard property dialog. */ 173 public static final String URI_PROPERTY_DIALOG = PATH_DIALOGS + "property_advanced.jsp"; 174 175 /** The URI to the property dialog handler. */ 176 public static final String URI_PROPERTY_DIALOG_HANDLER = PATH_DIALOGS + "property.jsp"; 177 178 /** The log object for this class. */ 179 private static final Log LOG = CmsLog.getLog(CmsPropertyAdvanced.class); 180 181 /** Holds all active properties for the current resource. */ 182 private Map<String, CmsProperty> m_activeProperties; 183 184 /** Parameters of this class. */ 185 private CmsParameterConfiguration m_handlerParams = new CmsParameterConfiguration(); 186 187 /** Helper object storing the current editable state of the resource. */ 188 private Boolean m_isEditable; 189 190 /** Helper to determine if the edited resource is a folder. */ 191 private boolean m_isFolder; 192 193 /** Helper stores the mode this dialog is in, because it can be called from "new" wizard. */ 194 private String m_paramDialogMode; 195 196 /** A parameter used by this dialog. */ 197 private String m_paramIndexPageType; 198 199 /** Request parameter members. */ 200 private String m_paramNewproperty; 201 202 /** A parameter used by this dialog. */ 203 private String m_paramUseTempfileProject; 204 205 /** Stores the values of properties in a String array. */ 206 private List<String[]> m_propertyValues; 207 208 /** Helper to determine if the user switched the tab views of the dialog. */ 209 private boolean m_tabSwitched; 210 211 /** The configured upload handler. */ 212 private I_CmsPostUploadDialogHandler m_uploadHandler = new CmsDefaultUploadHandler(); 213 214 /** 215 * Default constructor needed for dialog handler implementation.<p> 216 * 217 * Do not use this constructor on JSP pages.<p> 218 */ 219 public CmsPropertyAdvanced() { 220 221 super(null); 222 } 223 224 /** 225 * Public constructor with JSP action element.<p> 226 * 227 * @param jsp an initialized JSP action element 228 */ 229 public CmsPropertyAdvanced(CmsJspActionElement jsp) { 230 231 super(jsp); 232 } 233 234 /** 235 * Public constructor with JSP variables.<p> 236 * 237 * @param context the JSP page context 238 * @param req the JSP request 239 * @param res the JSP response 240 */ 241 public CmsPropertyAdvanced(PageContext context, HttpServletRequest req, HttpServletResponse res) { 242 243 this(new CmsJspActionElement(context, req, res)); 244 } 245 246 /** 247 * Transforms a list of CmsProperty objects with structure and resource values into a map with 248 * CmsProperty object values keyed by property keys.<p> 249 * 250 * @param list a list of CmsProperty objects 251 * @return a map with CmsPropery object values keyed by property keys 252 */ 253 public static Map<String, CmsProperty> getPropertyMap(List<CmsProperty> list) { 254 255 Map<String, CmsProperty> result = null; 256 String key = null; 257 CmsProperty property = null; 258 259 if ((list == null) || (list.size() == 0)) { 260 return Collections.emptyMap(); 261 } 262 263 result = new HashMap<String, CmsProperty>(); 264 265 // choose the fastest method to iterate the list 266 if (list instanceof RandomAccess) { 267 for (int i = 0, n = list.size(); i < n; i++) { 268 property = list.get(i); 269 key = property.getName(); 270 result.put(key, property); 271 } 272 } else { 273 Iterator<CmsProperty> i = list.iterator(); 274 while (i.hasNext()) { 275 property = i.next(); 276 key = property.getName(); 277 result.put(key, property); 278 } 279 } 280 281 return result; 282 } 283 284 /** 285 * Used to close the current JSP dialog.<p> 286 * 287 * This method overwrites the close dialog method in the super class, 288 * because in case a new folder is created, after this dialog a new xml page might be created.<p> 289 * 290 * It tries to include the URI stored in the workplace settings. 291 * This URI is determined by the frame name, which has to be set 292 * in the framename parameter.<p> 293 * 294 * @throws JspException if including an element fails 295 */ 296 @Override 297 public void actionCloseDialog() throws JspException { 298 299 if ((getAction() == ACTION_SAVE_EDIT) && MODE_WIZARD.equals(getParamDialogmode())) { 300 // set request attribute to reload the folder tree after creating a folder in wizard mode 301 try { 302 CmsResource res = getCms().readResource(getParamResource(), CmsResourceFilter.ALL); 303 if (res.isFolder()) { 304 List<String> folderList = new ArrayList<String>(1); 305 folderList.add(CmsResource.getParentFolder(getParamResource())); 306 getJsp().getRequest().setAttribute(REQUEST_ATTRIBUTE_RELOADTREE, folderList); 307 } 308 } catch (CmsException e) { 309 // should usually never happen 310 if (LOG.isInfoEnabled()) { 311 LOG.info(e.getLocalizedMessage()); 312 } 313 } 314 } else if (MODE_WIZARD_INDEXCREATED.equals(getParamDialogmode())) { 315 // set request attribute to reload the folder tree after creating an xml page in a new created folder in wizard mode 316 getSettings().setExplorerResource( 317 CmsResource.getParentFolder(CmsResource.getParentFolder(getParamResource())), 318 getCms()); 319 List<String> folderList = new ArrayList<String>(1); 320 folderList.add(CmsResource.getParentFolder(CmsResource.getParentFolder(getParamResource()))); 321 getJsp().getRequest().setAttribute(REQUEST_ATTRIBUTE_RELOADTREE, folderList); 322 } 323 super.actionCloseDialog(); 324 } 325 326 /** 327 * Performs the define property action, will be called by the JSP page.<p> 328 * 329 * @throws JspException if problems including sub-elements occur 330 */ 331 public void actionDefine() throws JspException { 332 333 // save initialized instance of this class in request attribute for included sub-elements 334 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 335 try { 336 performDefineOperation(); 337 // set the request parameters before returning to the overview 338 setParamAction(DIALOG_SHOW_DEFAULT); 339 setParamNewproperty(null); 340 sendForward(CmsWorkplace.VFS_PATH_COMMONS + "property_advanced.jsp", paramsAsParameterMap()); 341 } catch (Throwable e) { 342 // error defining property, show error dialog 343 includeErrorpage(this, e); 344 } 345 } 346 347 /** 348 * Deletes the current resource if the dialog is in wizard mode.<p> 349 * 350 * If the dialog is not in wizard mode, the resource is not deleted.<p> 351 * 352 * @throws JspException if including the error page fails 353 */ 354 public void actionDeleteResource() throws JspException { 355 356 if ((getParamDialogmode() != null) && getParamDialogmode().startsWith(MODE_WIZARD)) { 357 // only delete resource if dialog mode is a wizard mode 358 try { 359 getCms().deleteResource(getParamResource(), CmsResource.DELETE_PRESERVE_SIBLINGS); 360 } catch (Throwable e) { 361 // error deleting the resource, show error dialog 362 includeErrorpage(this, e); 363 } 364 } 365 } 366 367 /** 368 * Performs the edit properties action, will be called by the JSP page.<p> 369 * 370 * @param request the HttpServletRequest 371 * @throws JspException if problems including sub-elements occur 372 */ 373 public void actionEdit(HttpServletRequest request) throws JspException { 374 375 // save initialized instance of this class in request attribute for included sub-elements 376 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 377 try { 378 if (isEditable()) { 379 performDialogOperation(request); 380 } 381 } catch (Throwable e) { 382 // error editing property, show error dialog 383 includeErrorpage(this, e); 384 } 385 } 386 387 /** 388 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String) 389 */ 390 public void addConfigurationParameter(String paramName, String paramValue) { 391 392 if (m_handlerParams == null) { 393 m_handlerParams = new CmsParameterConfiguration(); 394 } 395 if (PARAM_HIDEADVANCED.equalsIgnoreCase(paramName)) { 396 m_handlerParams.add(PARAM_HIDEADVANCED, paramValue.trim()); 397 } 398 if (PARAM_SHOWGROUP.equalsIgnoreCase(paramName)) { 399 m_handlerParams.add(PARAM_SHOWGROUP, paramValue.trim()); 400 } 401 if (PARAM_POSTUPLOADHANDLER.equalsIgnoreCase(paramName)) { 402 m_handlerParams.add(PARAM_POSTUPLOADHANDLER, paramValue.trim()); 403 } 404 } 405 406 /** 407 * Creates the HTML String for the active properties overview of the current resource.<p> 408 * 409 * @return the HTML output String for active properties of the resource 410 */ 411 public String buildActivePropertiesList() { 412 413 StringBuffer retValue = new StringBuffer(256); 414 List<CmsPropertyDefinition> propertyDef = new ArrayList<CmsPropertyDefinition>(); 415 try { 416 // get all property definitions 417 propertyDef = getCms().readAllPropertyDefinitions(); 418 } catch (CmsException e) { 419 // should usually never happen 420 if (LOG.isInfoEnabled()) { 421 LOG.info(e.getLocalizedMessage()); 422 } 423 } 424 425 Iterator<CmsPropertyDefinition> j = propertyDef.iterator(); 426 int i = 0; 427 while (j.hasNext()) { 428 CmsPropertyDefinition curProperty = j.next(); 429 retValue.append(CmsEncoder.escapeXml(curProperty.getName())); 430 if ((i + 1) < propertyDef.size()) { 431 retValue.append("<br>"); 432 } 433 i++; 434 } 435 436 return retValue.toString(); 437 } 438 439 /** 440 * Creates the HTML String for the edit properties form.<p> 441 * 442 * The values of the form are set delayed, have a look at the 443 * JavaDoc of buildSetFormValues() for a detailed description.<p> 444 * 445 * @return the HTML output String for the edit properties form 446 */ 447 public String buildEditForm() { 448 449 StringBuffer result = new StringBuffer(4096); 450 451 // get currently active tab 452 String activeTab = getActiveTabName(); 453 454 // initialize "disabled" attribute for the input fields 455 String disabled = ""; 456 if (!isEditable()) { 457 disabled = " disabled=\"disabled\""; 458 } 459 460 // get all properties for the resource 461 List<String[]> properties = getPropertyValues(); 462 463 // check for presence of property definitions, should always be true 464 if (properties.size() > 0) { 465 // there are properties defined for this resource, build the form list 466 result.append("<table border=\"0\" style=\"width:100%\">\n"); 467 result.append("<tr>\n"); 468 result.append("\t<td class=\"textbold\" nowrap>"); 469 result.append(key(Messages.GUI_PROPERTY_0)); 470 result.append("</td>\n"); 471 result.append("\t<td class=\"textbold\">"); 472 result.append(key(Messages.GUI_PROPERTY_VALUE_0)); 473 result.append("</td>\n"); 474 // build column for checkbox 475 result.append("\t<td class=\"textbold\" style=\"white-space: nowrap;\">"); 476 result.append(" "); 477 result.append("</td>\n"); 478 result.append("</tr>\n"); 479 result.append("<tr><td colspan=\"3\"><span style=\"height: 6px;\"></span></td></tr>\n"); 480 481 // show all possible properties for the resource 482 Iterator<String[]> i = properties.iterator(); 483 while (i.hasNext()) { 484 String[] curProp = i.next(); 485 // create a single property row 486 result.append(buildPropertyRow(curProp[0], curProp[1], curProp[2], curProp[3], disabled, activeTab)); 487 } 488 result.append("</table>"); 489 } else { 490 // there are no properties defined for this resource, show nothing (should never happen) 491 result.append(key(Messages.GUI_PROPERTY_ADVANCED_NO_PROPDEFS_0)); 492 } 493 return result.toString(); 494 } 495 496 /** 497 * Builds the JavaScript to set the property form values delayed.<p> 498 * 499 * The values of the properties are not inserted directly in the <input> tag, 500 * because there is a display issue when the property values are very long. 501 * This method creates JavaScript to set the property input field values delayed. 502 * On the JSP, the code which is created from this method has to be executed delayed after 503 * the creation of the html form, e.g. in the <body> tag with the attribute 504 * onload="window.setTimeout('doSet()',50);".<p> 505 * 506 * @return the JavaScript to set the property form values delayed 507 */ 508 public String buildSetFormValues() { 509 510 StringBuffer result = new StringBuffer(1024); 511 // get currently active tab 512 String activeTab = getActiveTabName(); 513 // get structure panel name 514 String structurePanelName = key(Messages.GUI_PROPERTIES_INDIVIDUAL_0); 515 Iterator<String[]> i = getPropertyValues().iterator(); 516 while (i.hasNext()) { 517 String[] curProp = i.next(); 518 // determine the shown value 519 String shownValue = curProp[1]; 520 // in "shared properties" form, show resource value if no structure value is set 521 if (structurePanelName.equals(activeTab) && "".equals(curProp[2]) && !"".equals(curProp[3])) { 522 shownValue = curProp[3]; 523 } 524 if (!"".equals(shownValue)) { 525 // create the JS output for a single property if not empty 526 result.append("\tdocument.getElementById(\""); 527 result.append(PREFIX_VALUE); 528 result.append(curProp[0]); 529 result.append("\").value = \""); 530 result.append(CmsStringUtil.escapeJavaScript(shownValue)); 531 result.append("\";\n"); 532 } 533 534 } 535 return result.toString(); 536 } 537 538 /** 539 * Builds a button row with an "Ok", a "Cancel" and a "Define" button.<p> 540 * 541 * @return the button row 542 */ 543 public String dialogButtonsOkCancelDefine() { 544 545 if (isEditable()) { 546 int okButton = BUTTON_OK; 547 if ((getParamDialogmode() != null) && getParamDialogmode().startsWith(MODE_WIZARD)) { 548 // in wizard mode, display finish button instead of ok button 549 okButton = BUTTON_FINISH; 550 } 551 return dialogButtons( 552 new int[] {okButton, BUTTON_CANCEL, BUTTON_DEFINE}, 553 new String[] {null, null, "onclick=\"definePropertyForm();\""}); 554 } else { 555 return dialogButtons(new int[] {BUTTON_CLOSE}, new String[] {null}); 556 557 } 558 } 559 560 /** 561 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration() 562 */ 563 public CmsParameterConfiguration getConfiguration() { 564 565 if (m_handlerParams == null) { 566 m_handlerParams = new CmsParameterConfiguration(); 567 } 568 return m_handlerParams; 569 } 570 571 /** 572 * @see org.opencms.workplace.I_CmsDialogHandler#getDialogHandler() 573 */ 574 public String getDialogHandler() { 575 576 return CmsDialogSelector.DIALOG_PROPERTY; 577 } 578 579 /** 580 * @see org.opencms.workplace.I_CmsDialogHandler#getDialogUri(java.lang.String, CmsJspActionElement) 581 */ 582 public String getDialogUri(String resource, CmsJspActionElement jsp) { 583 584 try { 585 CmsResource res = jsp.getCmsObject().readResource(resource, CmsResourceFilter.ALL); 586 if (CmsResourceTypeXmlPage.isXmlPage(res)) { 587 // display special property dialog for xmlpage types 588 return PATH_WORKPLACE + "editors/dialogs/property.jsp"; 589 } 590 String resTypeName = OpenCms.getResourceManager().getResourceType(res.getTypeId()).getTypeName(); 591 // get settings for resource type 592 CmsExplorerTypeSettings settings = getSettingsForType(resTypeName); 593 if (settings.isPropertiesEnabled()) { 594 // special properties for this type enabled, display customized dialog 595 return URI_PROPERTY_CUSTOM_DIALOG; 596 } 597 } catch (CmsException e) { 598 // should usually never happen 599 if (LOG.isInfoEnabled()) { 600 LOG.info(e.getLocalizedMessage()); 601 } 602 } 603 return URI_PROPERTY_DIALOG; 604 } 605 606 /** 607 * Returns the value of the dialogmode parameter, 608 * or null if this parameter was not provided.<p> 609 * 610 * The dialogmode parameter stores the different modes of the property dialog, 611 * e.g. for displaying other buttons in the new resource wizard.<p> 612 * 613 * @return the value of the usetempfileproject parameter 614 */ 615 public String getParamDialogmode() { 616 617 return m_paramDialogMode; 618 } 619 620 /** 621 * Returns the paramIndexPageType.<p> 622 * 623 * @return the paramIndexPageType 624 */ 625 public String getParamIndexPageType() { 626 627 return m_paramIndexPageType; 628 } 629 630 /** 631 * Returns the value of the new property parameter, 632 * or null if this parameter was not provided.<p> 633 * 634 * The new property parameter stores the name of the 635 * new defined property.<p> 636 * 637 * @return the value of the new property parameter 638 */ 639 public String getParamNewproperty() { 640 641 return m_paramNewproperty; 642 } 643 644 /** 645 * Returns the value of the usetempfileproject parameter, 646 * or null if this parameter was not provided.<p> 647 * 648 * The usetempfileproject parameter stores if the file resides 649 * in the temp file project.<p> 650 * 651 * @return the value of the usetempfileproject parameter 652 */ 653 public String getParamUsetempfileproject() { 654 655 return m_paramUseTempfileProject; 656 } 657 658 /** 659 * @see org.opencms.workplace.CmsTabDialog#getTabParameterOrder() 660 */ 661 @Override 662 public List<String> getTabParameterOrder() { 663 664 ArrayList<String> orderList = new ArrayList<String>(2); 665 orderList.add(TAB_STRUCTURE); 666 orderList.add(TAB_RESOURCE); 667 return orderList; 668 } 669 670 /** 671 * @see org.opencms.workplace.CmsTabDialog#getTabs() 672 */ 673 @Override 674 public List<String> getTabs() { 675 676 ArrayList<String> tabList = new ArrayList<String>(2); 677 if (OpenCms.getWorkplaceManager().isEnableAdvancedPropertyTabs()) { 678 // tabs are enabled, show both tabs except for folders 679 if (m_isFolder) { 680 // resource is a folder, show only the individual properties tab 681 tabList.add(key(Messages.GUI_PROPERTIES_INDIVIDUAL_0)); 682 } else { 683 // resource is no folder, show both tabs 684 tabList.add(key(Messages.GUI_PROPERTIES_INDIVIDUAL_0)); 685 tabList.add(key(Messages.GUI_PROPERTIES_SHARED_0)); 686 } 687 } else { 688 // tabs are disabled, show only the configured tab except for folders 689 if (m_isFolder || OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { 690 tabList.add(key(Messages.GUI_PROPERTIES_INDIVIDUAL_0)); 691 } else { 692 tabList.add(key(Messages.GUI_PROPERTIES_SHARED_0)); 693 } 694 } 695 return tabList; 696 } 697 698 /** 699 * @see org.opencms.workplace.I_CmsPostUploadDialogHandler#getUploadHook(org.opencms.file.CmsObject, java.lang.String) 700 */ 701 public String getUploadHook(CmsObject cms, String uploadFolderSitePath) { 702 703 return m_uploadHandler.getUploadHook(cms, uploadFolderSitePath); 704 } 705 706 /** 707 * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration() 708 */ 709 public void initConfiguration() { 710 711 String uploadHandlerName = m_handlerParams.get(PARAM_POSTUPLOADHANDLER); 712 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(uploadHandlerName)) { 713 try { 714 Class<?> uploadHandlerClass = Class.forName(uploadHandlerName); 715 if (I_CmsPostUploadDialogHandler.class.isAssignableFrom(uploadHandlerClass)) { 716 m_uploadHandler = (I_CmsPostUploadDialogHandler)(uploadHandlerClass.newInstance()); 717 } else { 718 LOG.error("Invalid upload handler class: " + uploadHandlerName); 719 } 720 } catch (InstantiationException e) { 721 LOG.error("Could not instantiate upload handler: " + uploadHandlerName, e); 722 } catch (ClassNotFoundException e) { 723 LOG.error("Upload handler class not found: " + uploadHandlerName, e); 724 } catch (IllegalAccessException e) { 725 LOG.error(e.getLocalizedMessage(), e); 726 } 727 } 728 } 729 730 /** 731 * Sets the value of the dialogmode parameter.<p> 732 * 733 * @param value the value to set 734 */ 735 public void setParamDialogmode(String value) { 736 737 m_paramDialogMode = value; 738 } 739 740 /** 741 * Sets the paramIndexPageType.<p> 742 * 743 * @param paramIndexPageType the paramIndexPageType to set 744 */ 745 public void setParamIndexPageType(String paramIndexPageType) { 746 747 m_paramIndexPageType = paramIndexPageType; 748 } 749 750 /** 751 * Sets the value of the new property parameter.<p> 752 * 753 * @param value the value to set 754 */ 755 public void setParamNewproperty(String value) { 756 757 m_paramNewproperty = value; 758 } 759 760 /** 761 * Sets the value of the usetempfileproject parameter.<p> 762 * 763 * @param value the value to set 764 */ 765 public void setParamUsetempfileproject(String value) { 766 767 m_paramUseTempfileProject = value; 768 } 769 770 /** 771 * @see org.opencms.workplace.CmsDialog#dialogButtonsHtml(java.lang.StringBuffer, int, java.lang.String) 772 */ 773 @Override 774 protected void dialogButtonsHtml(StringBuffer result, int button, String attribute) { 775 776 attribute = appendDelimiter(attribute); 777 778 switch (button) { 779 case BUTTON_DEFINE: 780 result.append("<input name=\"define\" type=\"button\" value=\""); 781 result.append(key(Messages.GUI_PROPERTY_DEFINE_0)); 782 result.append("\" class=\"dialogbutton\""); 783 result.append(attribute); 784 result.append(">\n"); 785 break; 786 case BUTTON_FINISH: 787 result.append("<input name=\"finish\" type=\"submit\" value=\""); 788 result.append(key(Messages.GUI_PROPERTY_FINISH_0)); 789 result.append("\" class=\"dialogbutton\""); 790 result.append(attribute); 791 result.append(">\n"); 792 break; 793 default: 794 super.dialogButtonsHtml(result, button, attribute); 795 } 796 } 797 798 /** 799 * Returns a map with CmsProperty object values keyed by property keys.<p> 800 * 801 * @return a map with CmsProperty object values 802 */ 803 protected Map<String, CmsProperty> getActiveProperties() { 804 805 // get all used properties for the resource 806 if (m_activeProperties == null) { 807 try { 808 m_activeProperties = CmsPropertyAdvanced.getPropertyMap( 809 getCms().readPropertyObjects(getParamResource(), false)); 810 } catch (CmsException e) { 811 // create an empty list 812 if (LOG.isInfoEnabled()) { 813 LOG.info(e.getLocalizedMessage()); 814 } 815 m_activeProperties = new HashMap<String, CmsProperty>(); 816 } 817 } 818 return m_activeProperties; 819 } 820 821 /** 822 * Returns the explorer type settings of the resource type, considering eventual references to another type.<p> 823 * 824 * @param resTypeName the resource type name 825 * @return the explorer type settings of the resource type 826 */ 827 protected CmsExplorerTypeSettings getSettingsForType(String resTypeName) { 828 829 // get settings for resource type 830 CmsExplorerTypeSettings settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(resTypeName); 831 if (!settings.hasEditOptions() && CmsStringUtil.isNotEmpty(settings.getReference())) { 832 // refers to another resource type, get settings of referred type 833 settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(settings.getReference()); 834 } 835 return settings; 836 } 837 838 /** 839 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 840 */ 841 @Override 842 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 843 844 // fill the parameter values in the get/set methods 845 fillParamValues(request); 846 847 // get the active tab from request parameter or display first tab 848 getActiveTab(); 849 850 // check the resource type of the edited resource 851 m_isFolder = false; 852 try { 853 CmsResource resource = getCms().readResource(getParamResource(), CmsResourceFilter.ALL); 854 if (resource.isFolder()) { 855 m_isFolder = true; 856 if (!getParamResource().endsWith("/")) { 857 // append folder separator to resource name 858 setParamResource(getParamResource() + "/"); 859 } 860 } 861 } catch (CmsException e) { 862 // error reading resource, log the error 863 LOG.error(e.getLocalizedMessage()); 864 } 865 866 // set the dialog type 867 setParamDialogtype(DIALOG_TYPE); 868 boolean isPopup = Boolean.valueOf(getParamIsPopup()).booleanValue(); 869 // set the action for the JSP switch 870 if (DIALOG_SHOW_DEFINE.equals(getParamAction())) { 871 setAction(ACTION_SHOW_DEFINE); 872 setParamTitle(key(Messages.GUI_PROPERTY_NEW_DEF_1, new Object[] {CmsResource.getName(getParamResource())})); 873 } else if (DIALOG_SAVE_EDIT.equals(getParamAction())) { 874 if (isPopup) { 875 setAction(ACTION_CLOSEPOPUP_SAVE); 876 } else { 877 setAction(ACTION_SAVE_EDIT); 878 } 879 } else if (DIALOG_SAVE_DEFINE.equals(getParamAction())) { 880 setAction(ACTION_SAVE_DEFINE); 881 } else if (DIALOG_CANCEL.equals(getParamAction())) { 882 if (isPopup) { 883 setAction(ACTION_CLOSEPOPUP); 884 } else { 885 setAction(ACTION_CANCEL); 886 } 887 } else { 888 // set the default action: show edit form 889 setAction(ACTION_DEFAULT); 890 if (!isEditable()) { 891 setParamTitle( 892 key(Messages.GUI_PROPERTIES_OF_1, new Object[] {CmsResource.getName(getParamResource())})); 893 } else { 894 setParamTitle( 895 key(Messages.GUI_PROPERTIES_EDIT_1, new Object[] {CmsResource.getName(getParamResource())})); 896 } 897 // check if the user switched a tab 898 m_tabSwitched = false; 899 if (DIALOG_SWITCHTAB.equals(getParamAction())) { 900 m_tabSwitched = true; 901 } 902 } 903 } 904 905 /** 906 * Returns whether the properties are editable or not depending on the lock state of the resource and the current project.<p> 907 * 908 * @return true if properties are editable, otherwise false 909 */ 910 protected boolean isEditable() { 911 912 if (m_isEditable == null) { 913 914 if (getCms().getRequestContext().getCurrentProject().isOnlineProject() 915 || !getCms().isInsideCurrentProject(getParamResource())) { 916 // we are in the online project or resource does not belong to project, no editing allowed 917 m_isEditable = Boolean.FALSE; 918 919 } else { 920 // we are in an offline project 921 922 // check permissions 923 if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) { 924 getSettings().setErrorMessage(null); 925 m_isEditable = Boolean.FALSE; 926 return m_isEditable.booleanValue(); 927 } 928 929 // check lock state 930 String resourceName = getParamResource(); 931 CmsResource file = null; 932 CmsLock lock = null; 933 try { 934 file = getCms().readResource(resourceName, CmsResourceFilter.ALL); 935 // check if resource is a folder 936 if (file.isFolder() && !resourceName.endsWith("/")) { 937 resourceName += "/"; 938 } 939 } catch (CmsException e) { 940 // should usually never happen 941 if (LOG.isInfoEnabled()) { 942 LOG.info(e.getLocalizedMessage()); 943 } 944 } 945 946 try { 947 // get the lock for the resource 948 lock = getCms().getLock(file); 949 } catch (CmsException e) { 950 lock = CmsLock.getNullLock(); 951 952 if (LOG.isErrorEnabled()) { 953 LOG.error(e.getLocalizedMessage(), e); 954 } 955 } 956 957 if (!lock.isNullLock()) { 958 // determine if resource is editable... 959 if (lock.isDirectlyOwnedBy(getCms().getRequestContext().getCurrentUser())) { 960 // lock is exclusive and belongs to the current user 961 if (lock.isInProject(getCms().getRequestContext().getCurrentProject()) 962 || Boolean.valueOf(getParamUsetempfileproject()).booleanValue()) { 963 // resource is locked in the current project or the tempfileproject is used 964 m_isEditable = Boolean.TRUE; 965 return m_isEditable.booleanValue(); 966 } 967 } 968 } else if (OpenCms.getWorkplaceManager().autoLockResources()) { 969 if ((file == null) || file.isFolder()) { 970 // check locked resources in folder 971 try { 972 List<String> lockedResources = getCms().getLockedResources( 973 resourceName, 974 CmsLockFilter.FILTER_ALL.filterNotOwnedByUserId( 975 getCms().getRequestContext().getCurrentUser().getId())); 976 if (!lockedResources.isEmpty()) { 977 m_isEditable = Boolean.FALSE; 978 return m_isEditable.booleanValue(); 979 } 980 } catch (CmsException e1) { 981 // should usually never happen 982 if (LOG.isErrorEnabled()) { 983 LOG.error(e1.getLocalizedMessage(), e1); 984 } 985 } 986 } 987 m_isEditable = Boolean.TRUE; 988 return m_isEditable.booleanValue(); 989 } 990 // lock is null or belongs to other user and/or project, properties are not editable 991 m_isEditable = Boolean.FALSE; 992 } 993 } 994 return m_isEditable.booleanValue(); 995 } 996 997 /** 998 * Builds the html for a single property entry row.<p> 999 * 1000 * The output depends on the currently active tab (shared or individual properties) 1001 * and on the present values of the current property.<p> 1002 * 1003 * The values of the property are not inserted directly in the <input> tag, 1004 * because there is a display issue when the property values are very long. 1005 * Have a look at buildSetFormValues() for a detailed description.<p> 1006 * 1007 * @param propName the name of the property 1008 * @param propValue the displayed value of the property 1009 * @param valueStructure the structure value of the property 1010 * @param valueResource the resource value of the property 1011 * @param disabled contains attribute String to disable the fields 1012 * @param activeTab the name of the currently active dialog tab 1013 * @return the html for a single property entry row 1014 */ 1015 private StringBuffer buildPropertyRow( 1016 String propName, 1017 String propValue, 1018 String valueStructure, 1019 String valueResource, 1020 String disabled, 1021 String activeTab) { 1022 1023 StringBuffer result = new StringBuffer(256); 1024 // boolean existsPropertyValues = getActiveProperties().size() > 0; 1025 String structurePanelName = key(Messages.GUI_PROPERTIES_INDIVIDUAL_0); 1026 String inputAttrs = "class=\"maxwidth\""; 1027 if (structurePanelName.equals(activeTab)) { 1028 // in "shared properties" form, show resource value if no structure value is set 1029 if ("".equals(valueStructure) && !"".equals(valueResource)) { 1030 inputAttrs = "class=\"dialogmarkedfield\""; 1031 } 1032 } 1033 result.append("<tr>\n"); 1034 result.append("\t<td style=\"white-space: nowrap;\">" + propName); 1035 result.append("</td>\n"); 1036 result.append("\t<td class=\"maxwidth\">"); 1037 1038 // build text input field 1039 result.append("<input type=\"text\" "); 1040 result.append(inputAttrs); 1041 result.append(" name=\""); 1042 result.append(PREFIX_VALUE); 1043 result.append(propName); 1044 result.append("\" id=\""); 1045 result.append(PREFIX_VALUE); 1046 result.append(propName); 1047 result.append("\""); 1048 result.append(" onFocus=\"deleteResEntry('"); 1049 result.append(propName); 1050 result.append("', '"); 1051 result.append(activeTab); 1052 result.append("');\""); 1053 result.append(" onBlur=\"checkResEntry('"); 1054 result.append(propName); 1055 result.append("', '"); 1056 result.append(activeTab); 1057 result.append("');\" onKeyup=\"checkValue('"); 1058 result.append(propName); 1059 result.append("', '"); 1060 result.append(activeTab); 1061 result.append("');\""); 1062 result.append(disabled); 1063 result.append(">"); 1064 1065 // build hidden input field for structure value 1066 result.append("<input type=\"hidden\" name=\""); 1067 result.append(PREFIX_STRUCTURE); 1068 result.append(propName); 1069 result.append("\" id=\""); 1070 result.append(PREFIX_STRUCTURE); 1071 result.append(propName); 1072 result.append("\" value=\""); 1073 result.append(CmsEncoder.escapeXml(valueStructure)); 1074 result.append("\">"); 1075 1076 // build hidden input field for resource value 1077 result.append("<input type=\"hidden\" name=\""); 1078 result.append(PREFIX_RESOURCE); 1079 result.append(propName); 1080 result.append("\" id=\""); 1081 result.append(PREFIX_RESOURCE); 1082 result.append(propName); 1083 result.append("\" value=\""); 1084 result.append(CmsEncoder.escapeXml(valueResource)); 1085 result.append("\"></td>\n"); 1086 result.append("\t<td class=\"propertydialog-checkboxcell\">"); 1087 // show checkbox always 1088 String prefix = PREFIX_RESOURCE; 1089 if (structurePanelName.equals(activeTab)) { 1090 prefix = PREFIX_STRUCTURE; 1091 } 1092 result.append("<input type=\"checkbox\" name=\""); 1093 result.append(PREFIX_USEPROPERTY); 1094 result.append(propName); 1095 result.append("\" id=\""); 1096 result.append(PREFIX_USEPROPERTY); 1097 result.append(propName); 1098 result.append("\" value=\"true\""); 1099 result.append(disabled); 1100 if (CmsStringUtil.isNotEmpty(propValue)) { 1101 result.append(" checked=\"checked\" "); 1102 } 1103 result.append("onClick=\"toggleDelete('"); 1104 result.append(propName); 1105 result.append("', '"); 1106 result.append(prefix); 1107 result.append("', '"); 1108 result.append(activeTab); 1109 result.append("');\">"); 1110 result.append("</td>\n"); 1111 1112 result.append("</tr>\n"); 1113 return result; 1114 } 1115 1116 /** 1117 * Creates a list of String arrays containing the property names and values.<p> 1118 * 1119 * The list items consist of the following Strings: 1120 * <ol> 1121 * <li>The name of the property</li> 1122 * <li>The currently active property value</li> 1123 * <li>The value of the structure</li> 1124 * <li>The value of the resource</li> 1125 * </ol> 1126 * 1127 * @return the list of property values in display order 1128 */ 1129 private List<String[]> getPropertyValues() { 1130 1131 // check if list has to be generated 1132 if (m_propertyValues == null) { 1133 1134 // get currently active tab 1135 String activeTab = getActiveTabName(); 1136 String structurePanelName = key(Messages.GUI_PROPERTIES_INDIVIDUAL_0); 1137 1138 // get all properties for the resource 1139 List<CmsPropertyDefinition> propertyDef = new ArrayList<CmsPropertyDefinition>(); 1140 try { 1141 propertyDef = getCms().readAllPropertyDefinitions(); 1142 } catch (CmsException e) { 1143 // should usually never happen 1144 if (LOG.isInfoEnabled()) { 1145 LOG.info(e.getLocalizedMessage()); 1146 } 1147 } 1148 m_propertyValues = new ArrayList<String[]>(propertyDef.size()); 1149 1150 // get all used properties for the resource 1151 Map<String, CmsProperty> activeProperties = getActiveProperties(); 1152 1153 // iterate over all possible properties for the resource 1154 Iterator<CmsPropertyDefinition> i = propertyDef.iterator(); 1155 while (i.hasNext()) { 1156 CmsPropertyDefinition currentPropertyDef = i.next(); 1157 String propName = CmsEncoder.escapeXml(currentPropertyDef.getName()); 1158 String propValue = ""; 1159 String valueStructure = ""; 1160 String valueResource = ""; 1161 if (m_tabSwitched) { 1162 // switched the tab, get values from hidden fields 1163 if (structurePanelName.equals(activeTab)) { 1164 // structure form 1165 propValue = getJsp().getRequest().getParameter(PREFIX_STRUCTURE + propName); 1166 valueStructure = getJsp().getRequest().getParameter(PREFIX_STRUCTURE + propName); 1167 if (!isEditable()) { 1168 // values from disabled fields are not posted 1169 valueResource = getJsp().getRequest().getParameter(PREFIX_RESOURCE + propName); 1170 } else { 1171 valueResource = getJsp().getRequest().getParameter(PREFIX_VALUE + propName); 1172 } 1173 } else { 1174 // resource form 1175 propValue = getJsp().getRequest().getParameter(PREFIX_RESOURCE + propName); 1176 if (!isEditable()) { 1177 // values from disabled fields are not posted 1178 valueStructure = getJsp().getRequest().getParameter(PREFIX_STRUCTURE + propName); 1179 } else { 1180 valueStructure = getJsp().getRequest().getParameter(PREFIX_VALUE + propName); 1181 } 1182 valueResource = getJsp().getRequest().getParameter(PREFIX_RESOURCE + propName); 1183 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(valueStructure) 1184 && valueStructure.equals(valueResource)) { 1185 // the resource value was shown in the input field, set structure value to empty String 1186 valueStructure = ""; 1187 } 1188 } 1189 } else { 1190 // initial call of edit form, get property values from database 1191 CmsProperty currentProperty = activeProperties.get(propName); 1192 if (currentProperty == null) { 1193 currentProperty = new CmsProperty(); 1194 } 1195 if (structurePanelName.equals(activeTab)) { 1196 // show the structure properties 1197 propValue = currentProperty.getStructureValue(); 1198 } else { 1199 // show the resource properties 1200 propValue = currentProperty.getResourceValue(); 1201 } 1202 valueStructure = currentProperty.getStructureValue(); 1203 valueResource = currentProperty.getResourceValue(); 1204 } 1205 // check values for null 1206 if (propValue == null) { 1207 propValue = ""; 1208 } 1209 if (valueStructure == null) { 1210 valueStructure = ""; 1211 } 1212 if (valueResource == null) { 1213 valueResource = ""; 1214 } 1215 1216 // remove unnecessary blanks from values 1217 propValue = propValue.trim(); 1218 valueStructure = valueStructure.trim(); 1219 valueResource = valueResource.trim(); 1220 String[] property = new String[] {propName, propValue, valueStructure, valueResource}; 1221 m_propertyValues.add(property); 1222 } 1223 } 1224 // return the filled list 1225 return m_propertyValues; 1226 } 1227 1228 /** 1229 * Performs the definition of a new property.<p> 1230 * 1231 * @return true, if the new property was created, otherwise false 1232 * @throws CmsException if creation is not successful 1233 */ 1234 private boolean performDefineOperation() throws CmsException { 1235 1236 boolean useTempfileProject = Boolean.valueOf(getParamUsetempfileproject()).booleanValue(); 1237 try { 1238 if (useTempfileProject) { 1239 switchToTempProject(); 1240 } 1241 String newProperty = getParamNewproperty(); 1242 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(newProperty)) { 1243 getCms().createPropertyDefinition(newProperty); 1244 return true; 1245 } else { 1246 throw new CmsException(Messages.get().container(Messages.ERR_INVALID_PROP_0)); 1247 } 1248 } finally { 1249 if (useTempfileProject) { 1250 switchToCurrentProject(); 1251 } 1252 } 1253 } 1254 1255 /** 1256 * Performs the editing of the resources properties.<p> 1257 * 1258 * @param request the HttpServletRequest 1259 * @return true, if the properties were successfully changed, otherwise false 1260 * @throws CmsException if editing is not successful 1261 */ 1262 private boolean performDialogOperation(HttpServletRequest request) throws CmsException { 1263 1264 List<CmsPropertyDefinition> propertyDef = getCms().readAllPropertyDefinitions(); 1265 boolean useTempfileProject = Boolean.valueOf(getParamUsetempfileproject()).booleanValue(); 1266 try { 1267 if (useTempfileProject) { 1268 switchToTempProject(); 1269 } 1270 Map<String, CmsProperty> activeProperties = getActiveProperties(); 1271 String activeTab = getActiveTabName(); 1272 List<CmsProperty> propertiesToWrite = new ArrayList<CmsProperty>(); 1273 1274 // check all property definitions of the resource for new values 1275 Iterator<CmsPropertyDefinition> i = propertyDef.iterator(); 1276 while (i.hasNext()) { 1277 CmsPropertyDefinition curPropDef = i.next(); 1278 String propName = CmsEncoder.escapeXml(curPropDef.getName()); 1279 String valueStructure = null; 1280 String valueResource = null; 1281 1282 if (key(Messages.GUI_PROPERTIES_INDIVIDUAL_0).equals(activeTab)) { 1283 // get parameters from the structure tab 1284 valueStructure = request.getParameter(PREFIX_VALUE + propName); 1285 valueResource = request.getParameter(PREFIX_RESOURCE + propName); 1286 if ((valueStructure != null) 1287 && !"".equals(valueStructure.trim()) 1288 && valueStructure.equals(valueResource)) { 1289 // the resource value was shown/entered in input field, set structure value to empty String 1290 valueStructure = ""; 1291 } 1292 } else { 1293 // get parameters from the resource tab 1294 valueStructure = request.getParameter(PREFIX_STRUCTURE + propName); 1295 valueResource = request.getParameter(PREFIX_VALUE + propName); 1296 } 1297 1298 // check values for blanks and null 1299 if (valueStructure != null) { 1300 valueStructure = valueStructure.trim(); 1301 } 1302 1303 if (valueResource != null) { 1304 valueResource = valueResource.trim(); 1305 } 1306 1307 // create new CmsProperty object to store 1308 CmsProperty newProperty = new CmsProperty(); 1309 newProperty.setName(curPropDef.getName()); 1310 newProperty.setStructureValue(valueStructure); 1311 newProperty.setResourceValue(valueResource); 1312 1313 // get the old property values 1314 CmsProperty oldProperty = activeProperties.get(curPropDef.getName()); 1315 if (oldProperty == null) { 1316 // property was not set, create new empty property object 1317 oldProperty = new CmsProperty(); 1318 oldProperty.setName(curPropDef.getName()); 1319 } 1320 1321 boolean writeStructureValue = false; 1322 boolean writeResourceValue = false; 1323 String oldValue = oldProperty.getStructureValue(); 1324 String newValue = newProperty.getStructureValue(); 1325 1326 // write the structure value if the existing structure value is not null and we want to delete the structure value 1327 writeStructureValue = ((oldValue != null) && newProperty.isDeleteStructureValue()); 1328 // or if we want to write a value which is neither the delete value or an empty value 1329 writeStructureValue |= !newValue.equals(oldValue) 1330 && !"".equalsIgnoreCase(newValue) 1331 && !CmsProperty.DELETE_VALUE.equalsIgnoreCase(newValue); 1332 // set the structure value explicitly to null to leave it as is in the database 1333 if (!writeStructureValue) { 1334 newProperty.setStructureValue(null); 1335 } 1336 1337 oldValue = oldProperty.getResourceValue(); 1338 newValue = newProperty.getResourceValue(); 1339 1340 // write the resource value if the existing resource value is not null and we want to delete the resource value 1341 writeResourceValue = ((oldValue != null) && newProperty.isDeleteResourceValue()); 1342 // or if we want to write a value which is neither the delete value or an empty value 1343 writeResourceValue |= !newValue.equals(oldValue) 1344 && !"".equalsIgnoreCase(newValue) 1345 && !CmsProperty.DELETE_VALUE.equalsIgnoreCase(newValue); 1346 // set the resource value explicitly to null to leave it as is in the database 1347 if (!writeResourceValue) { 1348 newProperty.setResourceValue(null); 1349 } 1350 1351 if (writeStructureValue || writeResourceValue) { 1352 // add property to list only if property values have changed 1353 propertiesToWrite.add(newProperty); 1354 } 1355 } 1356 if (propertiesToWrite.size() > 0) { 1357 // lock resource if autolock is enabled 1358 checkLock(getParamResource()); 1359 //write the new property values 1360 getCms().writePropertyObjects(getParamResource(), propertiesToWrite); 1361 } 1362 } finally { 1363 if (useTempfileProject) { 1364 switchToCurrentProject(); 1365 } 1366 } 1367 return true; 1368 } 1369}