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.file.CmsObject; 031import org.opencms.file.CmsProperty; 032import org.opencms.file.CmsResource; 033import org.opencms.file.CmsResourceFilter; 034import org.opencms.file.types.I_CmsResourceType; 035import org.opencms.i18n.CmsEncoder; 036import org.opencms.jsp.CmsJspActionElement; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.main.OpenCms; 040import org.opencms.security.CmsPermissionSet; 041import org.opencms.util.CmsStringUtil; 042import org.opencms.workplace.CmsDialog; 043import org.opencms.workplace.CmsWorkplace; 044import org.opencms.workplace.CmsWorkplaceSettings; 045import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 046 047import java.util.Collections; 048import java.util.Iterator; 049import java.util.List; 050 051import javax.servlet.http.HttpServletRequest; 052import javax.servlet.http.HttpServletResponse; 053import javax.servlet.jsp.JspException; 054import javax.servlet.jsp.PageContext; 055 056import org.apache.commons.logging.Log; 057 058/** 059 * Provides methods for the multi file property edit action. 060 * <p> 061 * 062 * The following files use this class: 063 * <ul> 064 * <li>/commons/property_multifile.jsp 065 * </ul> 066 * <p> 067 * 068 * @since 7.5.1 069 */ 070public class CmsDialogMultiPropertyEdit extends CmsDialog { 071 072 /** Value for the action: comment images. */ 073 public static final int ACTION_MULTIFILEPROPERTYEDIT = 100; 074 075 /** The dialog type. */ 076 public static final String DIALOG_TYPE = "multifilepropertyedit"; 077 078 /** The input field prefix for description property fields. */ 079 public static final String PREFIX_DESCRIPTION = "desc_"; 080 081 /** The log object for this class. */ 082 private static final Log LOG = CmsLog.getLog(CmsDialogMultiPropertyEdit.class); 083 084 /** 085 * Public constructor with JSP action element. 086 * <p> 087 * 088 * @param jsp an initialized JSP action element 089 */ 090 public CmsDialogMultiPropertyEdit(final CmsJspActionElement jsp) { 091 092 super(jsp); 093 } 094 095 /** 096 * Public constructor with JSP variables. 097 * <p> 098 * 099 * @param context the JSP page context 100 * @param req the JSP request 101 * @param res the JSP response 102 */ 103 public CmsDialogMultiPropertyEdit( 104 final PageContext context, 105 final HttpServletRequest req, 106 final HttpServletResponse res) { 107 108 this(new CmsJspActionElement(context, req, res)); 109 } 110 111 /** 112 * Performs the comment files action, will be called by the JSP page. 113 * <p> 114 * 115 * @throws JspException if problems including sub-elements occur 116 */ 117 public void actionCommentImages() throws JspException { 118 119 // save initialized instance of this class in request attribute for included sub-elements 120 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 121 try { 122 performDialogOperation(); 123 // if no exception is caused comment operation was successful 124 actionCloseDialog(); 125 } catch (Throwable e) { 126 // error during rename images, show error dialog 127 includeErrorpage(this, e); 128 } 129 } 130 131 /** 132 * Returns the HTML for the dialog input form to comment the images. 133 * <p> 134 * 135 * @return the HTML for the dialog input form to comment the images 136 */ 137 public String buildDialogForm() { 138 139 StringBuffer result = new StringBuffer(16384); 140 List<CmsResource> resources = getResources(); 141 //Compute the height: 142 int amountOfInputFields = 4 * resources.size(); 143 int height = amountOfInputFields * 25; 144 // add padding for each resource grouping: 145 height += resources.size() * 30; 146 // add padding for whole dialog box: 147 height += 80; 148 // limit maximum height: 149 height = Math.min(height, 600); 150 151 Iterator<CmsResource> i = resources.iterator(); 152 153 result.append("<div style=\"height: ").append(height).append("px; padding: 4px; overflow: auto;\">"); 154 CmsResource res; 155 while (i.hasNext()) { 156 res = i.next(); 157 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(res); 158 // read the default properties for the given file type: 159 CmsExplorerTypeSettings settings = getSettingsForType(type.getTypeName()); 160 List<String> editProperties = settings.getProperties(); 161 if (editProperties.size() > 0) { 162 String iconPath = getSkinUri() + CmsWorkplace.RES_PATH_FILETYPES + settings.getIcon(); 163 String imageName = res.getName(); 164 String propertySuffix = "" + imageName.hashCode(); 165 result.append(dialogBlockStart("<img src=\"" + iconPath + "\"/> " + imageName)); 166 result.append("<table border=\"0\">\n"); 167 168 Iterator<String> itProperties = editProperties.iterator(); 169 String property; 170 while (itProperties.hasNext()) { 171 property = itProperties.next(); 172 result.append("<tr>\n"); 173 result.append("<td> </td>\n"); 174 // build title property input row 175 String title = ""; 176 try { 177 title = getCms().readPropertyObject(res, property, false).getValue(); 178 } catch (CmsException e) { 179 // log, should never happen 180 if (LOG.isErrorEnabled()) { 181 LOG.error(e.getLocalizedMessage(getLocale())); 182 } 183 } 184 result.append("<td style=\"white-space: nowrap;\" unselectable=\"on\" width=\"15%\">"); 185 result.append(property).append(": "); 186 result.append("</td>\n"); 187 result.append("<td class=\"maxwidth\">"); 188 result.append("<input type=\"text\" class=\"maxwidth\" name=\""); 189 result.append(property); 190 result.append(propertySuffix); 191 result.append("\" value=\""); 192 if (CmsStringUtil.isNotEmpty(title)) { 193 result.append(CmsEncoder.escapeXml(title)); 194 } 195 result.append("\""); 196 result.append(">"); 197 result.append("</td>\n</tr>\n"); 198 } 199 result.append("</table>\n"); 200 result.append(dialogBlockEnd()); 201 } 202 203 if (i.hasNext()) { 204 // append spacer if another entry follows 205 result.append(dialogSpacer()); 206 } 207 } 208 209 result.append("</div>"); 210 211 return result.toString(); 212 } 213 214 /** 215 * Returns the image resources of the gallery folder which are edited in the dialog form. 216 * <p> 217 * 218 * @return the images of the gallery folder which are edited in the dialog form 219 */ 220 protected List<CmsResource> getResources() { 221 222 List<CmsResource> result = Collections.emptyList(); 223 // get all image resources of the folder 224 CmsResourceFilter filter = CmsResourceFilter.DEFAULT; 225 try { 226 CmsObject cms = getCms(); 227 result = cms.readResources(getParamResource(), filter, false); 228 229 } catch (CmsException e) { 230 // log, should never happen 231 if (LOG.isErrorEnabled()) { 232 LOG.error(e.getLocalizedMessage(getLocale())); 233 } 234 } 235 return result; 236 } 237 238 /** 239 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, 240 * javax.servlet.http.HttpServletRequest) 241 */ 242 @Override 243 protected void initWorkplaceRequestValues(final CmsWorkplaceSettings settings, final HttpServletRequest request) { 244 245 // fill the parameter values in the get/set methods 246 fillParamValues(request); 247 248 // check the required permissions to rename the resource 249 if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) { 250 // no write permissions for the resource, set cancel action to close dialog 251 setParamAction(DIALOG_CANCEL); 252 } 253 254 // set the dialog type 255 setParamDialogtype(DIALOG_TYPE); 256 // set the action for the JSP switch 257 if (DIALOG_TYPE.equals(getParamAction())) { 258 setAction(ACTION_MULTIFILEPROPERTYEDIT); 259 } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) { 260 setAction(ACTION_LOCKS_CONFIRMED); 261 } else if (DIALOG_CANCEL.equals(getParamAction())) { 262 setAction(ACTION_CANCEL); 263 } else { 264 setAction(ACTION_DEFAULT); 265 // build title for comment images dialog 266 Object[] args = new Object[] {getParamResource()}; 267 setParamTitle(key(Messages.GUI_MULTIFILE_PROPERTY_TITLE_1, args)); 268 } 269 } 270 271 /** 272 * Performs the comment images operation. 273 * <p> 274 * 275 * @return true, if the resources were successfully processed, otherwise false 276 * @throws CmsException if commenting is not successful 277 */ 278 protected boolean performDialogOperation() throws CmsException { 279 280 // lock the folder 281 checkLock(getParamResource()); 282 283 Iterator<CmsResource> i = getResources().iterator(); 284 // loop over all image resources to change the properties 285 CmsResource res; 286 while (i.hasNext()) { 287 res = i.next(); 288 String imageName = res.getName(); 289 String propertySuffix = "" + imageName.hashCode(); 290 291 String property; 292 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(res); 293 CmsExplorerTypeSettings settings = getSettingsForType(type.getTypeName()); 294 Iterator<String> itProperties = settings.getProperties().iterator(); 295 while (itProperties.hasNext()) { 296 property = itProperties.next(); 297 CmsProperty currProperty = getCms().readPropertyObject(res, property, false); 298 String newValue = getJsp().getRequest().getParameter(property + propertySuffix); 299 writeProperty(res, property, newValue, currProperty); 300 } 301 } 302 303 // unlock the folder 304 CmsObject cms = getCms(); 305 cms.unlockResource(getParamResource()); 306 return true; 307 } 308 309 /** 310 * Writes a property value for a resource, if the value was changed. 311 * <p> 312 * 313 * @param res the resource to write the property to 314 * @param propName the name of the property definition 315 * @param propValue the new value of the property 316 * @param currentProperty the old property object 317 * @throws CmsException if something goes wrong 318 */ 319 protected void writeProperty( 320 final CmsResource res, 321 final String propName, 322 final String propValue, 323 final CmsProperty currentProperty) throws CmsException { 324 325 CmsProperty prop = currentProperty; 326 // check if current property is not the null property 327 if (prop.isNullProperty()) { 328 // create new property object 329 prop = new CmsProperty(); 330 prop.setName(propName); 331 } 332 333 if (CmsStringUtil.isEmptyOrWhitespaceOnly(propValue)) { 334 // parameter is empty, determine the value to delete 335 boolean writeProperty = false; 336 if (prop.getStructureValue() != null) { 337 prop.setStructureValue(CmsProperty.DELETE_VALUE); 338 prop.setResourceValue(null); 339 writeProperty = true; 340 } else if (prop.getResourceValue() != null) { 341 prop.setResourceValue(CmsProperty.DELETE_VALUE); 342 prop.setStructureValue(null); 343 writeProperty = true; 344 } 345 if (writeProperty) { 346 // write the updated property object 347 getCms().writePropertyObject(getCms().getSitePath(res), prop); 348 } 349 } else { 350 // parameter is not empty, check if the value has changed 351 if (!propValue.equals(prop.getValue())) { 352 if ((prop.getStructureValue() == null) && (prop.getResourceValue() == null)) { 353 // new property, determine setting from OpenCms workplace configuration 354 if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { 355 prop.setStructureValue(propValue); 356 prop.setResourceValue(null); 357 } else { 358 prop.setResourceValue(propValue); 359 prop.setStructureValue(null); 360 } 361 } else if (prop.getStructureValue() != null) { 362 // structure value has to be updated 363 prop.setStructureValue(propValue); 364 prop.setResourceValue(null); 365 } else { 366 // resource value has to be updated 367 prop.setResourceValue(propValue); 368 prop.setStructureValue(null); 369 } 370 // write the updated property object 371 getCms().writePropertyObject(getCms().getSitePath(res), prop); 372 } 373 } 374 } 375 376 /** 377 * Returns the explorer type settings of the resource type, considering eventual references to another type.<p> 378 * 379 * @param resTypeName the resource type name 380 * @return the explorer type settings of the resource type 381 */ 382 private CmsExplorerTypeSettings getSettingsForType(String resTypeName) { 383 384 // get settings for resource type 385 CmsExplorerTypeSettings settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(resTypeName); 386 if (!settings.hasEditOptions() && CmsStringUtil.isNotEmpty(settings.getReference())) { 387 // refers to another resource type, get settings of referred type 388 settings = OpenCms.getWorkplaceManager().getExplorerTypeSetting(settings.getReference()); 389 } 390 return settings; 391 } 392}