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.CmsProperty; 032import org.opencms.file.CmsPropertyDefinition; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.file.CmsUser; 036import org.opencms.i18n.CmsEncoder; 037import org.opencms.jsp.CmsJspActionElement; 038import org.opencms.main.CmsException; 039import org.opencms.main.CmsLog; 040import org.opencms.main.OpenCms; 041import org.opencms.security.CmsRole; 042import org.opencms.util.CmsStringUtil; 043import org.opencms.workplace.CmsWorkplaceSettings; 044import org.opencms.workplace.I_CmsDialogHandler; 045import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 046 047import java.util.Iterator; 048import java.util.List; 049 050import javax.servlet.http.HttpServletRequest; 051import javax.servlet.http.HttpServletResponse; 052import javax.servlet.jsp.JspException; 053import javax.servlet.jsp.PageContext; 054 055import org.apache.commons.logging.Log; 056 057/** 058 * Provides methods for the customized property dialog.<p> 059 * 060 * This is a special dialog that is used for the different resource types in the workplace.<p> 061 * For the xmlpage resource type, this class is extended in the editor subpackage.<p> 062 * 063 * The following files use this class: 064 * <ul> 065 * <li>/commons/property_custom.jsp 066 * </ul> 067 * <p> 068 * 069 * @since 6.0.0 070 */ 071public class CmsPropertyCustom extends CmsPropertyAdvanced { 072 073 /** Value for the action: edit the properties. */ 074 public static final int ACTION_EDIT = 500; 075 076 /** The log object for this class. */ 077 private static final Log LOG = CmsLog.getLog(CmsPropertyCustom.class); 078 079 /** Helper object holding the information about the customized properties. */ 080 private CmsExplorerTypeSettings m_explorerTypeSettings; 081 082 /** Flag to determine if navigation properties are shown. */ 083 private boolean m_showNavigation; 084 085 /** 086 * Public constructor with JSP action element.<p> 087 * 088 * @param jsp an initialized JSP action element 089 */ 090 public CmsPropertyCustom(CmsJspActionElement jsp) { 091 092 super(jsp); 093 } 094 095 /** 096 * Public constructor with JSP variables.<p> 097 * 098 * @param context the JSP page context 099 * @param req the JSP request 100 * @param res the JSP response 101 */ 102 public CmsPropertyCustom(PageContext context, HttpServletRequest req, HttpServletResponse res) { 103 104 this(new CmsJspActionElement(context, req, res)); 105 } 106 107 /** 108 * Performs the edit properties action, will be called by the JSP page.<p> 109 * 110 * @param request the HttpServletRequest 111 * @throws JspException if problems including sub-elements occur 112 */ 113 @Override 114 public void actionEdit(HttpServletRequest request) throws JspException { 115 116 // save initialized instance of this class in request attribute for included sub-elements 117 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 118 try { 119 // save the changes only if resource is properly locked 120 if (isEditable()) { 121 performEditOperation(request); 122 } 123 } catch (Throwable e) { 124 // Cms error defining property, show error dialog 125 includeErrorpage(this, e); 126 } 127 } 128 129 /** 130 * Creates the HTML String for the edit properties form.<p> 131 * 132 * @return the HTML output String for the edit properties form 133 */ 134 @Override 135 public String buildEditForm() { 136 137 StringBuffer result = new StringBuffer(2048); 138 139 // check if the properties are editable 140 boolean editable = isEditable(); 141 142 // create the column heads 143 result.append("<table border=\"0\" style=\"width:100%\">\n"); 144 result.append("<tr>\n"); 145 result.append("\t<td class=\"textbold\" nowrap>"); 146 result.append(key(Messages.GUI_PROPERTY_0)); 147 result.append("</td>\n"); 148 result.append("\t<td class=\"textbold\">"); 149 result.append(key(Messages.GUI_PROPERTY_VALUE_0)); 150 result.append("</td>\n"); 151 // empty column for the checkboxes 152 result.append("\t<td class=\"textbold\" style=\"white-space: nowrap;\">"); 153 result.append(" "); 154 result.append("</td>\n"); 155 result.append("</tr>\n"); 156 result.append("<tr><td><span style=\"height: 6px;\"></span></td></tr>\n"); 157 158 // create the text property input rows from explorer type settings 159 result.append(buildTextInput(editable)); 160 161 // show navigation properties if enabled in explorer type settings 162 if (showNavigation()) { 163 result.append(buildNavigationProperties(editable)); 164 } 165 result.append("</table>"); 166 167 return result.toString(); 168 } 169 170 /** 171 * Builds the JavaScript to set the property form values delayed.<p> 172 * 173 * The values of the properties are not inserted directly in the <input> tag, 174 * because there is a display issue when the property values are very long. 175 * This method creates JavaScript to set the property input field values delayed. 176 * On the JSP, the code which is created from this method has to be executed delayed after 177 * the creation of the html form, e.g. in the <body> tag with the attribute 178 * onload="window.setTimeout('doSet()',50);".<p> 179 * 180 * @return the JavaScript to set the property form values delayed 181 */ 182 @Override 183 public String buildSetFormValues() { 184 185 StringBuffer result = new StringBuffer(1024); 186 Iterator<String> i = getExplorerTypeSettings().getProperties().iterator(); 187 // iterate over the customized properties 188 while (i.hasNext()) { 189 String curProperty = i.next(); 190 if (getActiveProperties().containsKey(curProperty)) { 191 CmsProperty property = getActiveProperties().get(curProperty); 192 String propValue = property.getValue(); 193 if (propValue != null) { 194 propValue = propValue.trim(); 195 propValue = CmsStringUtil.escapeJavaScript(propValue); 196 // create the JS output for a single property 197 result.append("\tdocument.getElementById(\""); 198 result.append(PREFIX_VALUE); 199 result.append(curProperty); 200 result.append("\").value = \""); 201 result.append(propValue); 202 result.append("\";\n"); 203 } 204 } 205 } 206 // check if the navigation text property value has to be added 207 if (showNavigation() && getActiveProperties().containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT)) { 208 CmsProperty property = getActiveProperties().get(CmsPropertyDefinition.PROPERTY_NAVTEXT); 209 String propValue = property.getValue(); 210 if (propValue != null) { 211 propValue = propValue.trim(); 212 propValue = CmsStringUtil.escapeJavaScript(propValue); 213 // create the JS output for a single property 214 result.append("\tdocument.getElementById(\""); 215 result.append(PREFIX_VALUE); 216 result.append(CmsPropertyDefinition.PROPERTY_NAVTEXT); 217 result.append("\").value = \""); 218 result.append(propValue); 219 result.append("\";\n"); 220 } 221 } 222 return result.toString(); 223 } 224 225 /** 226 * Builds a button row with an "ok", a "cancel" and an "advanced" button.<p> 227 * 228 * @param okAttributes additional attributes for the "ok" button 229 * @param cancelAttributes additional attributes for the "cancel" button 230 * @param advancedAttributes additional attributes for the "advanced" button 231 * @return the button row 232 */ 233 @Override 234 public String dialogButtonsOkCancelAdvanced( 235 String okAttributes, 236 String cancelAttributes, 237 String advancedAttributes) { 238 239 if (isEditable()) { 240 int okButton = BUTTON_OK; 241 if ((getParamDialogmode() != null) && getParamDialogmode().startsWith(MODE_WIZARD)) { 242 // in wizard mode, display finish button instead of ok button 243 okButton = BUTTON_FINISH; 244 } 245 // hide "advanced" button 246 if (isHideButtonAdvanced()) { 247 return dialogButtons( 248 new int[] {okButton, BUTTON_CANCEL}, 249 new String[] {okAttributes, cancelAttributes}); 250 } 251 // show "advanced" button 252 return dialogButtons( 253 new int[] {okButton, BUTTON_CANCEL, BUTTON_ADVANCED}, 254 new String[] {okAttributes, cancelAttributes, advancedAttributes}); 255 } else { 256 // hide "advanced" button 257 if (isHideButtonAdvanced()) { 258 return dialogButtons(new int[] {BUTTON_CLOSE}, new String[] {cancelAttributes}); 259 } 260 // show "advanced" button 261 return dialogButtons( 262 new int[] {BUTTON_CLOSE, BUTTON_ADVANCED}, 263 new String[] {cancelAttributes, advancedAttributes}); 264 } 265 } 266 267 /** 268 * Returns the explorer type settings for the current resource type.<p> 269 * 270 * @return the explorer type settings for the current resource type 271 */ 272 public CmsExplorerTypeSettings getExplorerTypeSettings() { 273 274 return m_explorerTypeSettings; 275 } 276 277 /** 278 * Sets the explorer type settings for the current resource type.<p> 279 * 280 * @param typeSettings the explorer type settings for the current resource type 281 */ 282 public void setExplorerTypeSettings(CmsExplorerTypeSettings typeSettings) { 283 284 m_explorerTypeSettings = typeSettings; 285 } 286 287 /** 288 * Sets if navigation properties are shown.<p> 289 * 290 * @param showNav true, if navigation properties are shown, otherwise false 291 */ 292 public void setShowNavigation(boolean showNav) { 293 294 m_showNavigation = showNav; 295 } 296 297 /** 298 * Returns if navigation properties are shown.<p> 299 * 300 * @return true, if navigation properties are shown, otherwise false 301 */ 302 public boolean showNavigation() { 303 304 return m_showNavigation; 305 } 306 307 /** 308 * Builds the HTML code for the special properties of an xmlpage resource.<p> 309 * 310 * @param editable indicates if the properties are editable 311 * @return the HTML code for the special properties of a file resource 312 */ 313 protected StringBuffer buildNavigationProperties(boolean editable) { 314 315 StringBuffer result = new StringBuffer(1024); 316 317 // create "disabled" attribute if properties are not editable 318 String disabled = ""; 319 if (!editable) { 320 disabled = " disabled=\"disabled\""; 321 } 322 323 // create "add to navigation" checkbox 324 result.append(buildTableRowStart(key(Messages.GUI_PROPERTY_ADD_TO_NAV_0))); 325 result.append( 326 "<input type=\"checkbox\" name=\"enablenav\" id=\"enablenav\" value=\"true\" onClick=\"toggleNav();\""); 327 if (getActiveProperties().containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT) 328 || getActiveProperties().containsKey(CmsPropertyDefinition.PROPERTY_NAVPOS)) { 329 result.append(" checked=\"checked\""); 330 } 331 result.append(disabled); 332 result.append(">"); 333 result.append("</td>\n"); 334 result.append("\t<td class=\"textcenter\">"); 335 result.append(" "); 336 result.append(buildTableRowEnd()); 337 338 // create NavText input row 339 result.append( 340 buildPropertyEntry(CmsPropertyDefinition.PROPERTY_NAVTEXT, key(Messages.GUI_LABEL_NAVTEXT_0), editable)); 341 342 // create NavPos select box row 343 result.append(buildTableRowStart(key(Messages.GUI_CHNAV_INSERT_AFTER_0))); 344 result.append(CmsChnav.buildNavPosSelector( 345 getCms(), 346 getParamResource(), 347 disabled + " id=\"navpos\" class=\"maxwidth noborder\"", 348 getMessages())); 349 // get the old NavPos value and store it in hidden field 350 String navPos = null; 351 try { 352 navPos = getCms().readPropertyObject( 353 getParamResource(), 354 CmsPropertyDefinition.PROPERTY_NAVPOS, 355 false).getValue(); 356 } catch (CmsException e) { 357 // should usually never happen 358 if (LOG.isInfoEnabled()) { 359 LOG.info(e.getLocalizedMessage()); 360 } 361 } 362 if (navPos == null) { 363 navPos = ""; 364 } 365 result.append("<input type=\"hidden\" name=\""); 366 result.append(PREFIX_HIDDEN); 367 result.append(CmsPropertyDefinition.PROPERTY_NAVPOS); 368 result.append("\" value=\""); 369 result.append(navPos); 370 result.append("\">"); 371 result.append("</td>\n"); 372 result.append("\t<td class=\"textcenter\">"); 373 result.append(" "); 374 result.append(buildTableRowEnd()); 375 376 return result; 377 } 378 379 /** 380 * Builds the html for a single text input property row.<p> 381 * 382 * The html does not include the value of the created property, 383 * the values are set delayed (see buildSetFormValues() for details).<p> 384 * 385 * @param propertyName the name of the property 386 * @param propertyTitle the nice name of the property 387 * @param editable indicates if the properties are editable 388 * @return the html for a single text input property row 389 */ 390 protected StringBuffer buildPropertyEntry(String propertyName, String propertyTitle, boolean editable) { 391 392 StringBuffer result = new StringBuffer(256); 393 // create "disabled" attribute if properties are not editable 394 String disabled = ""; 395 if (!editable) { 396 disabled = " disabled=\"disabled\""; 397 } 398 result.append(buildTableRowStart(propertyTitle)); 399 // the property is used, so create text field with checkbox and hidden field 400 CmsProperty currentProperty = getActiveProperties().get(propertyName); 401 String propValue = ""; 402 if (currentProperty != null) { 403 propValue = currentProperty.getValue(); 404 } 405 if (propValue != null) { 406 propValue = propValue.trim(); 407 } 408 propValue = CmsEncoder.escapeXml(propValue); 409 410 // create text input field 411 result.append("<input type=\"text\" class=\"maxwidth\""); 412 result.append(" name=\""); 413 result.append(PREFIX_VALUE); 414 result.append(propertyName); 415 result.append("\" id=\""); 416 result.append(PREFIX_VALUE); 417 result.append(propertyName); 418 result.append("\""); 419 if (editable) { 420 result.append(" onKeyup=\"checkValue('"); 421 result.append(propertyName); 422 result.append("');\""); 423 } 424 result.append(disabled); 425 result.append(">"); 426 427 // create hidden field for value 428 result.append("<input type=\"hidden\" name=\""); 429 result.append(PREFIX_HIDDEN); 430 result.append(propertyName); 431 result.append("\" id=\""); 432 result.append(PREFIX_HIDDEN); 433 result.append(propertyName); 434 result.append("\" value=\""); 435 result.append(propValue); 436 result.append("\">"); 437 result.append("</td>\n"); 438 result.append("\t<td class=\"propertydialog-checkboxcell\">"); 439 440 // create activate/deactivate checkbox 441 result.append("<input type=\"checkbox\" name=\""); 442 result.append(PREFIX_USEPROPERTY); 443 result.append(propertyName); 444 result.append("\" id=\""); 445 result.append(PREFIX_USEPROPERTY); 446 result.append(propertyName); 447 result.append("\" value=\"true\""); 448 if (CmsStringUtil.isNotEmpty(propValue)) { 449 result.append(" checked=\"checked\""); 450 } 451 if (editable) { 452 result.append(" onClick=\"toggleDelete('"); 453 result.append(propertyName); 454 result.append("');\""); 455 } 456 result.append(disabled + ">"); 457 458 result.append(buildTableRowEnd()); 459 return result; 460 } 461 462 /** 463 * Builds the HTML for the end of a table row for a single property.<p> 464 * 465 * @return the HTML code for a table row end 466 */ 467 protected String buildTableRowEnd() { 468 469 return "</td>\n</tr>\n"; 470 } 471 472 /** 473 * Builds the HTML for the start of a table row for a single property.<p> 474 * 475 * @param propertyName the name of the current property 476 * @return the HTML code for the start of a table row 477 */ 478 protected StringBuffer buildTableRowStart(String propertyName) { 479 480 StringBuffer result = new StringBuffer(96); 481 result.append("<tr>\n"); 482 result.append("\t<td style=\"white-space: nowrap;\" unselectable=\"on\">"); 483 result.append(propertyName); 484 result.append("</td>\n"); 485 result.append("\t<td class=\"maxwidth\">"); 486 return result; 487 } 488 489 /** 490 * Builds the HTML for the common text input property values stored in the String array "PROPERTIES".<p> 491 * 492 * @param editable indicates if the properties are editable 493 * @return the HTML code for the common text input fields 494 */ 495 protected StringBuffer buildTextInput(boolean editable) { 496 497 StringBuffer result = new StringBuffer(256); 498 Iterator<String> i = getExplorerTypeSettings().getProperties().iterator(); 499 // iterate over the properties 500 while (i.hasNext()) { 501 String curProperty = i.next(); 502 result.append(buildPropertyEntry(curProperty, curProperty, editable)); 503 } 504 return result; 505 } 506 507 /** 508 * Initializes the explorer type settings for the current resource type.<p> 509 */ 510 protected void initExplorerTypeSettings() { 511 512 try { 513 CmsResource res = getCms().readResource(getParamResource(), CmsResourceFilter.ALL); 514 if (res.isFolder()) { 515 if (!getParamResource().endsWith("/")) { 516 // append folder separator to resource name 517 setParamResource(getParamResource() + "/"); 518 } 519 } 520 String resTypeName = OpenCms.getResourceManager().getResourceType(res.getTypeId()).getTypeName(); 521 // get settings for resource type 522 setExplorerTypeSettings(getSettingsForType(resTypeName)); 523 setShowNavigation(getExplorerTypeSettings().isShowNavigation()); 524 } catch (Throwable e) { 525 // error reading file, show error dialog 526 try { 527 includeErrorpage(this, e); 528 } catch (JspException exc) { 529 LOG.error( 530 Messages.get().getBundle().key(Messages.LOG_ERROR_INCLUDE_FAILED_1, FILE_DIALOG_SCREEN_ERRORPAGE)); 531 } 532 } 533 } 534 535 /** 536 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 537 */ 538 @Override 539 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 540 541 // fill the parameter values in the get/set methods 542 fillParamValues(request); 543 // get the explorer type settings for the current resource 544 initExplorerTypeSettings(); 545 // set the dialog type 546 setParamDialogtype(DIALOG_TYPE); 547 boolean isPopup = Boolean.valueOf(getParamIsPopup()).booleanValue(); 548 // set the action for the JSP switch 549 if (DIALOG_SHOW_DEFAULT.equals(getParamAction())) { 550 // save changed properties and redirect to the default OpenCms dialog 551 setAction(ACTION_DEFAULT); 552 try { 553 actionEdit(request); 554 sendForward(CmsPropertyAdvanced.URI_PROPERTY_DIALOG, paramsAsParameterMap()); 555 return; 556 } catch (Exception e) { 557 // should usually never happen 558 if (LOG.isInfoEnabled()) { 559 LOG.info(e.getLocalizedMessage()); 560 } 561 } 562 } else if (DIALOG_SAVE_EDIT.equals(getParamAction())) { 563 // save the edited properties 564 if (isPopup) { 565 setAction(ACTION_CLOSEPOPUP_SAVE); 566 } else { 567 setAction(ACTION_SAVE_EDIT); 568 } 569 } else if (DIALOG_CANCEL.equals(getParamAction())) { 570 // save the edited properties 571 if (isPopup) { 572 setAction(ACTION_CLOSEPOPUP); 573 } else { 574 setAction(ACTION_CANCEL); 575 } 576 } else { 577 setAction(ACTION_EDIT); 578 String resName = CmsResource.getName(getParamResource()); 579 if (CmsResource.isTemporaryFileName(resName)) { 580 resName = resName.substring(1); 581 } 582 setParamTitle(key(Messages.GUI_PROPERTIES_1, new Object[] {resName})); 583 } 584 } 585 586 /** 587 * Checks the optional parameters of the handler configuration. <p> 588 * 589 * Decides if the "advanced" button should be shown or not. 590 * The "advanced" button is shown if no parameters are given (default) 591 * or the "hideadvanced" attribute is set to false. The "advanced" button 592 * is hidden only, if "hideadvanced" is true and the user is not a member 593 * of the specified user groups. 594 * 595 * @return false if the "advanced" button is shown (default) <br> 596 * true if the "advanced" button is hidden 597 */ 598 protected boolean isHideButtonAdvanced() { 599 600 I_CmsDialogHandler handler = OpenCms.getWorkplaceManager().getDialogHandler(getDialogHandler()); 601 CmsParameterConfiguration handlerParams = handler.getConfiguration(); 602 if ((handlerParams != null) && handlerParams.containsKey(PARAM_HIDEADVANCED)) { 603 // checks if "hideadvanced" is set to true 604 boolean isHideAdvancedSet = false; 605 List<String> hAdvanced = handlerParams.getList(PARAM_HIDEADVANCED); 606 if (!hAdvanced.isEmpty()) { 607 isHideAdvancedSet = Boolean.valueOf(hAdvanced.get(0)).booleanValue(); 608 } 609 if (isHideAdvancedSet) { 610 // if user has the role root admin 611 if (OpenCms.getRoleManager().hasRole(getCms(), CmsRole.ROOT_ADMIN)) { 612 return false; 613 } 614 if (handlerParams.containsKey(PARAM_SHOWGROUP)) { 615 // check if user is one of the configured groups 616 CmsUser currentUser = getCms().getRequestContext().getCurrentUser(); 617 List<String> confGroups = handlerParams.getList(PARAM_SHOWGROUP); 618 for (String groupName : confGroups) { 619 try { 620 if (getCms().userInGroup(currentUser.getName(), groupName)) { 621 return false; 622 } 623 } catch (CmsException e) { 624 LOG.error(e.getLocalizedMessage(), e); 625 } 626 } 627 } 628 return true; 629 } 630 } 631 return false; 632 } 633 634 /** 635 * Performs the editing of the resources properties.<p> 636 * 637 * @param request the HttpServletRequest 638 * @return true, if the properties were successfully changed, otherwise false 639 * @throws CmsException if editing is not successful 640 */ 641 protected boolean performEditOperation(HttpServletRequest request) throws CmsException { 642 643 boolean useTempfileProject = Boolean.valueOf(getParamUsetempfileproject()).booleanValue(); 644 try { 645 if (useTempfileProject) { 646 switchToTempProject(); 647 } 648 // write the common properties defined in the explorer type settings 649 Iterator<String> i = getExplorerTypeSettings().getProperties().iterator(); 650 // iterate over the properties 651 while (i.hasNext()) { 652 String curProperty = i.next(); 653 String paramValue = request.getParameter(PREFIX_VALUE + curProperty); 654 String oldValue = request.getParameter(PREFIX_HIDDEN + curProperty); 655 writeProperty(curProperty, paramValue, oldValue); 656 } 657 658 // write the navigation properties if enabled 659 if (showNavigation()) { 660 // get the navigation enabled parameter 661 String paramValue = request.getParameter("enablenav"); 662 String oldValue = null; 663 if (Boolean.valueOf(paramValue).booleanValue()) { 664 // navigation enabled, update params 665 paramValue = request.getParameter("navpos"); 666 if (!"-1".equals(paramValue) && !String.valueOf(Float.MAX_VALUE).equals(paramValue)) { 667 // update the property only when it is different from "-1" (meaning no change) 668 oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_NAVPOS); 669 writeProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, paramValue, oldValue); 670 } 671 paramValue = request.getParameter(PREFIX_VALUE + CmsPropertyDefinition.PROPERTY_NAVTEXT); 672 oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_NAVTEXT); 673 writeProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT, paramValue, oldValue); 674 } else { 675 // navigation disabled, delete property values 676 writeProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, null, null); 677 writeProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT, null, null); 678 } 679 } 680 } finally { 681 if (useTempfileProject) { 682 switchToCurrentProject(); 683 } 684 } 685 return true; 686 } 687 688 /** 689 * Writes a property value for a resource, if the value was changed.<p> 690 * 691 * If a property definition for the resource does not exist, 692 * it is automatically created by this method.<p> 693 * 694 * @param propName the name of the property 695 * @param propValue the new value of the property 696 * @param oldValue the old value of the property 697 * @throws CmsException if something goes wrong 698 */ 699 protected void writeProperty(String propName, String propValue, String oldValue) throws CmsException { 700 701 // get the current property object 702 CmsProperty currentProperty = getActiveProperties().get(propName); 703 if (currentProperty == null) { 704 // new property, create new property object 705 currentProperty = new CmsProperty(); 706 currentProperty.setName(propName); 707 } else { 708 // clone the property, because the original property is frozen 709 currentProperty = currentProperty.cloneAsProperty(); 710 } 711 712 // check if there is a parameter value for the current property 713 boolean emptyParam = true; 714 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(propValue)) { 715 emptyParam = false; 716 } 717 718 if (emptyParam) { 719 // parameter is empty, check if the property has to be deleted 720 if (getActiveProperties().containsKey(propName)) { 721 // lock resource if autolock is enabled 722 checkLock(getParamResource()); 723 // determine the value to delete 724 if (currentProperty.getStructureValue() != null) { 725 currentProperty.setStructureValue(CmsProperty.DELETE_VALUE); 726 currentProperty.setResourceValue(null); 727 } else { 728 currentProperty.setResourceValue(CmsProperty.DELETE_VALUE); 729 currentProperty.setStructureValue(null); 730 } 731 // write the updated property object 732 getCms().writePropertyObject(getParamResource(), currentProperty); 733 } 734 } else { 735 // parameter is not empty, check if the value has changed 736 if (!propValue.equals(oldValue)) { 737 // lock resource if autolock is enabled 738 checkLock(getParamResource()); 739 if ((currentProperty.getStructureValue() == null) && (currentProperty.getResourceValue() == null)) { 740 // new property, determine setting from OpenCms workplace configuration 741 if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { 742 currentProperty.setStructureValue(propValue); 743 currentProperty.setResourceValue(null); 744 } else { 745 currentProperty.setResourceValue(propValue); 746 currentProperty.setStructureValue(null); 747 } 748 } else if (currentProperty.getStructureValue() != null) { 749 // structure value has to be updated 750 currentProperty.setStructureValue(propValue); 751 currentProperty.setResourceValue(null); 752 } else { 753 // resource value has to be updated 754 currentProperty.setResourceValue(propValue); 755 currentProperty.setStructureValue(null); 756 } 757 // set auto-creation of the property to true 758 currentProperty.setAutoCreatePropertyDefinition(true); 759 // write the updated property object 760 getCms().writePropertyObject(getParamResource(), currentProperty); 761 } 762 } 763 } 764}