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 com.alkacon.simapi.Simapi; 031 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.CmsResourceTypeImage; 037import org.opencms.i18n.CmsEncoder; 038import org.opencms.jsp.CmsJspActionElement; 039import org.opencms.loader.CmsImageScaler; 040import org.opencms.loader.CmsLoaderException; 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.CmsDialog; 047import org.opencms.workplace.CmsWorkplaceSettings; 048 049import java.awt.Color; 050import java.util.Collections; 051import java.util.Iterator; 052import java.util.List; 053 054import javax.servlet.http.HttpServletRequest; 055import javax.servlet.http.HttpServletResponse; 056import javax.servlet.jsp.JspException; 057import javax.servlet.jsp.PageContext; 058 059import org.apache.commons.logging.Log; 060 061/** 062 * Provides methods for the comment images dialog on image gallery folders.<p> 063 * 064 * The following files use this class: 065 * <ul> 066 * <li>/commons/commentimages.jsp 067 * </ul> 068 * <p> 069 * 070 * @since 6.1.3 071 */ 072public class CmsCommentImages extends CmsDialog { 073 074 /** Value for the action: comment images. */ 075 public static final int ACTION_COMMENTIMAGES = 100; 076 077 /** The dialog type. */ 078 public static final String DIALOG_TYPE = "commentimages"; 079 080 /** The input field prefix for description property fields. */ 081 public static final String PREFIX_DESCRIPTION = "desc_"; 082 083 /** The input field prefix for title property fields. */ 084 public static final String PREFIX_TITLE = "title_"; 085 086 /** The height of the dialog thumbnails. */ 087 public static final int THUMB_HEIGHT = 150; 088 089 /** The width of the dialog thumbnails. */ 090 public static final int THUMB_WIDTH = 200; 091 092 /** The log object for this class. */ 093 private static final Log LOG = CmsLog.getLog(CmsCommentImages.class); 094 095 /** The image scaler object used in the dialog input form. */ 096 private CmsImageScaler m_imageScaler; 097 098 /** 099 * Public constructor with JSP action element.<p> 100 * 101 * @param jsp an initialized JSP action element 102 */ 103 public CmsCommentImages(CmsJspActionElement jsp) { 104 105 super(jsp); 106 } 107 108 /** 109 * Public constructor with JSP variables.<p> 110 * 111 * @param context the JSP page context 112 * @param req the JSP request 113 * @param res the JSP response 114 */ 115 public CmsCommentImages(PageContext context, HttpServletRequest req, HttpServletResponse res) { 116 117 this(new CmsJspActionElement(context, req, res)); 118 } 119 120 /** 121 * Performs the comment images action, will be called by the JSP page.<p> 122 * 123 * @throws JspException if problems including sub-elements occur 124 */ 125 public void actionCommentImages() throws JspException { 126 127 // save initialized instance of this class in request attribute for included sub-elements 128 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 129 try { 130 performDialogOperation(); 131 // if no exception is caused comment operation was successful 132 actionCloseDialog(); 133 } catch (Throwable e) { 134 // error during rename images, show error dialog 135 includeErrorpage(this, e); 136 } 137 } 138 139 /** 140 * Returns the HTML for the dialog input form to comment the images.<p> 141 * 142 * @return the HTML for the dialog input form to comment the images 143 */ 144 public String buildDialogForm() { 145 146 StringBuffer result = new StringBuffer(16384); 147 Iterator<CmsResource> i = getImages().iterator(); 148 149 result.append("<div style=\"height: 450px; padding: 4px; overflow: auto;\">"); 150 151 while (i.hasNext()) { 152 CmsResource res = i.next(); 153 String imageName = res.getName(); 154 String propertySuffix = "" + imageName.hashCode(); 155 result.append(dialogBlockStart(imageName)); 156 result.append("<table border=\"0\">\n"); 157 result.append("<tr>\n\t<td style=\"vertical-align: top;\">"); 158 // create image tag 159 result.append("<img src=\""); 160 StringBuffer link = new StringBuffer(256); 161 link.append(getCms().getSitePath(res)); 162 link.append(getImageScaler().toRequestParam()); 163 result.append(getJsp().link(link.toString())); 164 result.append("\" border=\"0\" alt=\"\" width=\""); 165 result.append(getImageScaler().getWidth()); 166 result.append("\" height=\""); 167 result.append(getImageScaler().getHeight()); 168 result.append("\">"); 169 170 result.append("</td>\n"); 171 result.append("\t<td class=\"maxwidth\" style=\"vertical-align: top;\">\n"); 172 173 result.append("\t\t<table border=\"0\">\n"); 174 175 // build title property input row 176 String title = ""; 177 try { 178 title = getCms().readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(); 179 } catch (CmsException e) { 180 // log, should never happen 181 if (LOG.isErrorEnabled()) { 182 LOG.error(e.getLocalizedMessage(getLocale())); 183 } 184 } 185 result.append("\t\t<tr>\n\t\t\t<td style=\"white-space: nowrap;\" unselectable=\"on\">"); 186 result.append(key(Messages.GUI_LABEL_TITLE_0)); 187 result.append(":</td>\n\t\t\t<td class=\"maxwidth\">"); 188 result.append("<input type=\"text\" class=\"maxwidth\" name=\""); 189 result.append(PREFIX_TITLE); 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("</td>\n\t\t</tr>\n"); 197 198 // build description property input row 199 String description = ""; 200 try { 201 description = getCms().readPropertyObject( 202 res, 203 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 204 false).getValue(); 205 } catch (CmsException e) { 206 // log, should never happen 207 if (LOG.isErrorEnabled()) { 208 LOG.error(e.getLocalizedMessage(getLocale())); 209 } 210 } 211 result.append( 212 "\t\t<tr>\n\t\t\t<td style=\"white-space: nowrap; vertical-align: top;\" unselectable=\"on\">"); 213 result.append(key(Messages.GUI_LABEL_DESCRIPTION_0)); 214 result.append(":</td>\n\t\t\t<td style=\"vertical-align: top; height: 110px;\">"); 215 result.append("<textarea rows=\"8\" class=\"maxwidth\" style=\"overflow: auto;\" name=\""); 216 result.append(PREFIX_DESCRIPTION); 217 result.append(propertySuffix); 218 result.append("\">"); 219 if (CmsStringUtil.isNotEmpty(description)) { 220 result.append(CmsEncoder.escapeXml(description)); 221 } 222 result.append("</textarea>"); 223 result.append("</td>\n\t\t</tr>\n"); 224 225 result.append("\t\t</table>\n"); 226 227 result.append("</td>\n</tr>\n"); 228 result.append("</table>\n"); 229 result.append(dialogBlockEnd()); 230 231 if (i.hasNext()) { 232 // append spacer if another entry follows 233 result.append(dialogSpacer()); 234 } 235 } 236 237 result.append("</div>"); 238 239 return result.toString(); 240 } 241 242 /** 243 * Returns the image resources of the gallery folder which are edited in the dialog form.<p> 244 * 245 * @return the images of the gallery folder which are edited in the dialog form 246 */ 247 protected List<CmsResource> getImages() { 248 249 // get all image resources of the folder 250 int imageId; 251 try { 252 imageId = OpenCms.getResourceManager().getResourceType( 253 CmsResourceTypeImage.getStaticTypeName()).getTypeId(); 254 } catch (CmsLoaderException e1) { 255 // should really never happen 256 LOG.warn(e1.getLocalizedMessage(), e1); 257 imageId = CmsResourceTypeImage.getStaticTypeId(); 258 } 259 CmsResourceFilter filter = CmsResourceFilter.IGNORE_EXPIRATION.addRequireType(imageId); 260 try { 261 return getCms().readResources(getParamResource(), filter, false); 262 } catch (CmsException e) { 263 // log, should never happen 264 if (LOG.isErrorEnabled()) { 265 LOG.error(e.getLocalizedMessage(getLocale())); 266 } 267 return Collections.emptyList(); 268 } 269 } 270 271 /** 272 * Returns the initialized image scaler object used to generate thumbnails for the dialog form.<p> 273 * 274 * @return the initialized image scaler object used to generate thumbnails for the dialog form 275 */ 276 protected CmsImageScaler getImageScaler() { 277 278 if (m_imageScaler == null) { 279 // not initialized, create image scaler with default settings 280 m_imageScaler = new CmsImageScaler(); 281 m_imageScaler.setWidth(THUMB_WIDTH); 282 m_imageScaler.setHeight(THUMB_HEIGHT); 283 m_imageScaler.setRenderMode(Simapi.RENDER_SPEED); 284 m_imageScaler.setColor(new Color(0, 0, 0)); 285 m_imageScaler.setType(1); 286 } 287 return m_imageScaler; 288 } 289 290 /** 291 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 292 */ 293 @Override 294 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 295 296 // fill the parameter values in the get/set methods 297 fillParamValues(request); 298 299 // check the required permissions to rename the resource 300 if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE, false)) { 301 // no write permissions for the resource, set cancel action to close dialog 302 setParamAction(DIALOG_CANCEL); 303 } 304 305 // set the dialog type 306 setParamDialogtype(DIALOG_TYPE); 307 // set the action for the JSP switch 308 if (DIALOG_TYPE.equals(getParamAction())) { 309 setAction(ACTION_COMMENTIMAGES); 310 } else if (DIALOG_LOCKS_CONFIRMED.equals(getParamAction())) { 311 setAction(ACTION_LOCKS_CONFIRMED); 312 } else if (DIALOG_CANCEL.equals(getParamAction())) { 313 setAction(ACTION_CANCEL); 314 } else { 315 setAction(ACTION_DEFAULT); 316 // build title for comment images dialog 317 Object[] args = new Object[] {getParamResource()}; 318 setParamTitle(key(Messages.GUI_COMMENTIMAGES_TITLE_1, args)); 319 } 320 } 321 322 /** 323 * Performs the comment images operation.<p> 324 * 325 * @return true, if the resources were successfully processed, otherwise false 326 * @throws CmsException if commenting is not successful 327 */ 328 protected boolean performDialogOperation() throws CmsException { 329 330 // lock the image gallery folder 331 checkLock(getParamResource()); 332 333 Iterator<CmsResource> i = getImages().iterator(); 334 // loop over all image resources to change the properties 335 while (i.hasNext()) { 336 CmsResource res = i.next(); 337 String imageName = res.getName(); 338 String propertySuffix = "" + imageName.hashCode(); 339 340 // update the title property 341 CmsProperty titleProperty = getCms().readPropertyObject(res, CmsPropertyDefinition.PROPERTY_TITLE, false); 342 String newValue = getJsp().getRequest().getParameter(PREFIX_TITLE + propertySuffix); 343 writeProperty(res, CmsPropertyDefinition.PROPERTY_TITLE, newValue, titleProperty); 344 345 // update the description property 346 CmsProperty descProperty = getCms().readPropertyObject( 347 res, 348 CmsPropertyDefinition.PROPERTY_DESCRIPTION, 349 false); 350 newValue = getJsp().getRequest().getParameter(PREFIX_DESCRIPTION + propertySuffix); 351 writeProperty(res, CmsPropertyDefinition.PROPERTY_DESCRIPTION, newValue, descProperty); 352 } 353 354 return true; 355 } 356 357 /** 358 * Writes a property value for a resource, if the value was changed.<p> 359 * 360 * @param res the resource to write the property to 361 * @param propName the name of the property definition 362 * @param propValue the new value of the property 363 * @param currentProperty the old property object 364 * @throws CmsException if something goes wrong 365 */ 366 protected void writeProperty(CmsResource res, String propName, String propValue, CmsProperty currentProperty) 367 throws CmsException { 368 369 // check if current property is not the null property 370 if (currentProperty.isNullProperty()) { 371 // create new property object 372 currentProperty = new CmsProperty(); 373 currentProperty.setName(propName); 374 } 375 376 if (CmsStringUtil.isEmptyOrWhitespaceOnly(propValue)) { 377 // parameter is empty, determine the value to delete 378 boolean writeProperty = false; 379 if (currentProperty.getStructureValue() != null) { 380 currentProperty.setStructureValue(CmsProperty.DELETE_VALUE); 381 currentProperty.setResourceValue(null); 382 writeProperty = true; 383 } else if (currentProperty.getResourceValue() != null) { 384 currentProperty.setResourceValue(CmsProperty.DELETE_VALUE); 385 currentProperty.setStructureValue(null); 386 writeProperty = true; 387 } 388 if (writeProperty) { 389 // write the updated property object 390 getCms().writePropertyObject(getCms().getSitePath(res), currentProperty); 391 } 392 } else { 393 // parameter is not empty, check if the value has changed 394 if (!propValue.equals(currentProperty.getValue())) { 395 if ((currentProperty.getStructureValue() == null) && (currentProperty.getResourceValue() == null)) { 396 // new property, determine setting from OpenCms workplace configuration 397 if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { 398 currentProperty.setStructureValue(propValue); 399 currentProperty.setResourceValue(null); 400 } else { 401 currentProperty.setResourceValue(propValue); 402 currentProperty.setStructureValue(null); 403 } 404 } else if (currentProperty.getStructureValue() != null) { 405 // structure value has to be updated 406 currentProperty.setStructureValue(propValue); 407 currentProperty.setResourceValue(null); 408 } else { 409 // resource value has to be updated 410 currentProperty.setResourceValue(propValue); 411 currentProperty.setStructureValue(null); 412 } 413 // write the updated property object 414 getCms().writePropertyObject(getCms().getSitePath(res), currentProperty); 415 } 416 } 417 } 418 419}