001: /*
002: * File : $Source: /usr/local/cvs/opencms/src-modules/org/opencms/workplace/tools/content/CmsPropertyChange.java,v $
003: * Date : $Date: 2008-02-27 12:05:37 $
004: * Version: $Revision: 1.18 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.workplace.tools.content;
033:
034: import org.opencms.file.CmsObject;
035: import org.opencms.file.CmsProperty;
036: import org.opencms.file.CmsPropertyDefinition;
037: import org.opencms.file.CmsResource;
038: import org.opencms.file.CmsResourceFilter;
039: import org.opencms.file.CmsVfsException;
040: import org.opencms.i18n.CmsEncoder;
041: import org.opencms.i18n.CmsMessages;
042: import org.opencms.jsp.CmsJspActionElement;
043: import org.opencms.main.CmsException;
044: import org.opencms.main.CmsLog;
045: import org.opencms.util.CmsStringUtil;
046: import org.opencms.workplace.CmsDialog;
047: import org.opencms.workplace.CmsWorkplaceSettings;
048:
049: import java.util.ArrayList;
050: import java.util.List;
051: import java.util.regex.Pattern;
052: import java.util.regex.PatternSyntaxException;
053:
054: import javax.servlet.http.HttpServletRequest;
055: import javax.servlet.http.HttpServletResponse;
056: import javax.servlet.jsp.JspException;
057: import javax.servlet.jsp.PageContext;
058:
059: import org.apache.commons.logging.Log;
060:
061: /**
062: * Provides methods for the change property values dialog.<p>
063: *
064: * @author Andreas Zahner
065: *
066: * @version $Revision: 1.18 $
067: *
068: * @since 6.0.0
069: */
070: public class CmsPropertyChange extends CmsDialog {
071:
072: /** Value for the action: show result. */
073: public static final int ACTION_SHOWRESULT = 100;
074:
075: /** Request parameter value for the action: show result. */
076: public static final String DIALOG_SHOWRESULT = "showresult";
077:
078: /** The dialog type. */
079: public static final String DIALOG_TYPE = "propertychange";
080: /** Request parameter name for the property name. */
081: public static final String PARAM_NEWVALUE = "newvalue";
082: /** Request parameter name for the property name. */
083: public static final String PARAM_OLDVALUE = "oldvalue";
084: /** Request parameter name for the property name. */
085: public static final String PARAM_PROPERTYNAME = "propertyname";
086: /** Request parameter name for the property name. */
087: public static final String PARAM_RECURSIVE = "recursive";
088:
089: /** The log object for this class. */
090: private static final Log LOG = CmsLog
091: .getLog(CmsPropertyChange.class);
092:
093: private List m_changedResources;
094:
095: /** The error message. */
096: private String m_errorMessage;
097:
098: private String m_paramNewValue;
099: private String m_paramOldValue;
100: private String m_paramPropertyName;
101: private String m_paramRecursive;
102:
103: private boolean m_validationErrors;
104:
105: /**
106: * Public constructor with JSP action element.<p>
107: *
108: * @param jsp an initialized JSP action element
109: */
110: public CmsPropertyChange(CmsJspActionElement jsp) {
111:
112: super (jsp);
113: }
114:
115: /**
116: * Public constructor with JSP variables.<p>
117: *
118: * @param context the JSP page context
119: * @param req the JSP request
120: * @param res the JSP response
121: */
122: public CmsPropertyChange(PageContext context,
123: HttpServletRequest req, HttpServletResponse res) {
124:
125: this (new CmsJspActionElement(context, req, res));
126: }
127:
128: /**
129: * Builds the html for the property definition select box.<p>
130: *
131: * @param cms the CmsObject
132: * @param selectValue the localized value for the "Please select" option
133: * @param attributes optional attributes for the <select> tag
134: * @param selectedValue the value that is currently selected
135: * @return the html for the property definition select box
136: */
137: public static String buildSelectProperty(CmsObject cms,
138: String selectValue, String attributes, String selectedValue) {
139:
140: List propertyDef = new ArrayList();
141: try {
142: // get all property definitions
143: propertyDef = cms.readAllPropertyDefinitions();
144: } catch (CmsException e) {
145: // should usually never happen
146: if (LOG.isInfoEnabled()) {
147: LOG.info(e);
148: }
149: }
150:
151: int propertyCount = propertyDef.size();
152: List options = new ArrayList(propertyCount + 1);
153: List values = new ArrayList(propertyCount + 1);
154: options.add(CmsEncoder.escapeXml(selectValue));
155: values.add("");
156: int selectedIndex = 0;
157: int count = 1;
158:
159: for (int i = 0; i < propertyCount; i++) {
160: // loop property definitions and get definition name
161: CmsPropertyDefinition currDef = (CmsPropertyDefinition) propertyDef
162: .get(i);
163: if (currDef.getName().equals(selectedValue)) {
164: selectedIndex = count;
165: }
166: options.add(CmsEncoder.escapeXml(currDef.getName()));
167: values.add(CmsEncoder.escapeXml(currDef.getName()));
168: count += 1;
169: }
170:
171: CmsDialog wp = new CmsDialog(null);
172: return wp.buildSelect(attributes, options, values,
173: selectedIndex);
174: }
175:
176: /**
177: * Changes the property values on the specified resources.<p>
178: *
179: * @throws JspException if problems including sub-elements occur
180: */
181: public void actionChange() throws JspException {
182:
183: // save initialized instance of this class in request attribute for included sub-elements
184: getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS,
185: this );
186: try {
187: boolean recursive = Boolean.valueOf(getParamRecursive())
188: .booleanValue();
189: if (performChangeOperation(recursive)) {
190: // if no exception is caused and "true" is returned change property operation was successful
191: setAction(ACTION_SHOWRESULT);
192: } else {
193: // "false" returned, display "please wait" screen
194: getJsp().include(FILE_DIALOG_SCREEN_WAIT);
195: }
196: } catch (Throwable e) {
197: // error while changing property values, show error dialog
198: includeErrorpage(this , e);
199:
200: }
201: }
202:
203: /**
204: * Builds the html for the result list of resources where the property was changed.<p>
205: *
206: * @return the html for the result list
207: */
208: public String buildResultList() {
209:
210: StringBuffer result = new StringBuffer(16);
211: if (getChangedResources() != null
212: && getChangedResources().size() > 0) {
213: // at least one resource property value has been changed, show list
214: for (int i = 0; i < getChangedResources().size(); i++) {
215: CmsResource res = (CmsResource) getChangedResources()
216: .get(i);
217: String resName = getCms().getSitePath(res);
218: result.append(resName);
219: result.append("<br>\n");
220: }
221: } else {
222: // nothing was changed, show message
223: result.append(Messages.get().getBundle(getLocale()).key(
224: Messages.GUI_INPUT_PROPERTYCHANGE_RESULT_NONE_0));
225: }
226: return result.toString();
227: }
228:
229: /**
230: * Builds the html for the property definition select box.<p>
231: *
232: * @param attributes optional attributes for the <select> tag
233: * @return the html for the property definition select box
234: */
235: public String buildSelectProperty(String attributes) {
236:
237: return buildSelectProperty(getCms(), Messages.get().getBundle(
238: getLocale()).key(Messages.GUI_PLEASE_SELECT_0),
239: attributes, getParamPropertyName());
240: }
241:
242: /**
243: * Returns the error message.<p>
244: *
245: * @return the error message
246: */
247: public String getErrorMessage() {
248:
249: if (CmsStringUtil.isEmpty(m_errorMessage)) {
250: return "";
251: }
252:
253: return m_errorMessage;
254: }
255:
256: /**
257: * Returns the value of the newvalue parameter.<p>
258: *
259: * @return the value of the newvalue parameter
260: */
261: public String getParamNewValue() {
262:
263: if (m_paramNewValue != null) {
264: return m_paramNewValue;
265: } else {
266: return CmsProperty.DELETE_VALUE;
267: }
268: }
269:
270: /**
271: * Returns the value of the oldvalue parametere.<p>
272: *
273: * @return the value of the oldvalue parameter
274: */
275: public String getParamOldValue() {
276:
277: return m_paramOldValue;
278: }
279:
280: /**
281: * Returns the value of the propertyname parameter.<p>
282: *
283: * @return the value of the propertyname parameter
284: */
285: public String getParamPropertyName() {
286:
287: return m_paramPropertyName;
288: }
289:
290: /**
291: * Returns the value of the recursive parameter.<p>
292: *
293: * @return the value of the recursive parameter
294: */
295: public String getParamRecursive() {
296:
297: return m_paramRecursive;
298: }
299:
300: /**
301: * Returns the height for the result list of changed resources.<p>
302: *
303: * @return the height for the result list of changed resources
304: */
305: public String getResultListHeight() {
306:
307: if (getChangedResources() != null
308: && getChangedResources().size() > 0) {
309: int height = getChangedResources().size() * 14;
310: if (height > 300) {
311: height = 300;
312: }
313: return "" + height;
314: } else {
315: return "14";
316: }
317: }
318:
319: /**
320: * Returns if validation errors were found.<p>
321: *
322: * @return true if validation errors were found, otherwise false
323: */
324: public boolean hasValidationErrors() {
325:
326: return m_validationErrors;
327: }
328:
329: /**
330: * Sets the value of the newvalue parameter.<p>
331: *
332: * @param paramNewValue the value of the newvalue parameter
333: */
334: public void setParamNewValue(String paramNewValue) {
335:
336: m_paramNewValue = paramNewValue;
337: }
338:
339: /**
340: * Sets the value of the oldvalue parameter.<p>
341: *
342: * @param paramOldValue the value of the oldvalue parameter
343: */
344: public void setParamOldValue(String paramOldValue) {
345:
346: m_paramOldValue = paramOldValue;
347: }
348:
349: /**
350: * Sets the value of the propertyname parameter.<p>
351: *
352: * @param paramPropertyName the value of the propertyname parameter
353: */
354: public void setParamPropertyName(String paramPropertyName) {
355:
356: m_paramPropertyName = paramPropertyName;
357: }
358:
359: /**
360: * Sets the value of the recursive parameter.<p>
361: *
362: * @param paramRecursive the value of the recursive parameter
363: */
364: public void setParamRecursive(String paramRecursive) {
365:
366: m_paramRecursive = paramRecursive;
367: }
368:
369: /**
370: * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
371: */
372: protected void initWorkplaceRequestValues(
373: CmsWorkplaceSettings settings, HttpServletRequest request) {
374:
375: // fill the parameter values in the get/set methods
376: fillParamValues(request);
377: // set the dialog type
378: setParamDialogtype(DIALOG_TYPE);
379: // set the action for the JSP switch
380: if (DIALOG_OK.equals(getParamAction())) {
381: if (validateParameters()) {
382: // all parameters are valid, proceed
383: setAction(ACTION_OK);
384: } else {
385: // validation error(s), redisplay form
386: setAction(ACTION_DEFAULT);
387: }
388: } else if (DIALOG_WAIT.equals(getParamAction())) {
389: setAction(ACTION_WAIT);
390: } else if (DIALOG_CANCEL.equals(getParamAction())) {
391: setAction(ACTION_CANCEL);
392: } else {
393: setAction(ACTION_DEFAULT);
394: // build title for change property value dialog
395: setParamTitle(Messages.get().getBundle(getLocale()).key(
396: Messages.GUI_TITLE_PROPERTYCHANGE_0));
397: }
398: }
399:
400: /**
401: * Sets the error message.<p>
402: *
403: * @param errorMessage the error message to set
404: */
405: protected void setErrorMessage(String errorMessage) {
406:
407: m_errorMessage = errorMessage;
408: }
409:
410: /**
411: * Sets the validation error flag.<p>
412: *
413: * @param validationErrors the validation error flag, true if validation errors were found
414: */
415: protected void setValidationErrors(boolean validationErrors) {
416:
417: m_validationErrors = validationErrors;
418: }
419:
420: /**
421: * Returns the changed resources that were affected by the property change action.<p>
422: *
423: * @return the changed resources that were affected by the property change action
424: */
425: private List getChangedResources() {
426:
427: return m_changedResources;
428: }
429:
430: /**
431: * Performs the main property change value operation on the resource property.<p>
432: *
433: * @param recursive true, if the property value has to be changed recursively, otherwise false
434: * @return true, if the property values are changed successfully, otherwise false
435: * @throws CmsException if changing is not successful
436: */
437: private boolean performChangeOperation(boolean recursive)
438: throws CmsException {
439:
440: // on recursive property changes display "please wait" screen
441: if (recursive && !DIALOG_WAIT.equals(getParamAction())) {
442: // return false, this will trigger the "please wait" screen
443: return false;
444: }
445:
446: // lock the selected resource
447: checkLock(getParamResource());
448: // change the property values
449: List changedResources = null;
450: if (CmsStringUtil
451: .isNotEmptyOrWhitespaceOnly(getParamOldValue())) {
452: changedResources = getCms()
453: .changeResourcesInFolderWithProperty(
454: getParamResource(), getParamPropertyName(),
455: getParamOldValue(), getParamNewValue(),
456: recursive);
457: } else {
458: changedResources = setPropertyInFolder(getParamResource(),
459: getParamPropertyName(), getParamNewValue(),
460: recursive);
461: }
462: setChangedResources(changedResources);
463: return true;
464: }
465:
466: /**
467: * Sets the given property with the given value to the given resource
468: * (potentially recursiv) if it has not been set before.<p>
469: *
470: * Returns a list with all sub resources that have been modified this way.<p>
471: *
472: * @param resourceRootPath the resource on which property definition values are changed
473: * @param propertyDefinition the name of the propertydefinition to change the value
474: * @param newValue the new value of the propertydefinition
475: * @param recursive if true, change recursively all property values on sub-resources (only for folders)
476: *
477: * @return a list with the <code>{@link CmsResource}</code>'s where the property value has been changed
478: *
479: * @throws CmsVfsException for now only when the search for the oldvalue failed.
480: * @throws CmsException if operation was not successful
481: */
482: private List setPropertyInFolder(String resourceRootPath,
483: String propertyDefinition, String newValue,
484: boolean recursive) throws CmsException, CmsVfsException {
485:
486: CmsObject cms = this .getCms();
487:
488: // collect the resources to look up
489: List resources = new ArrayList();
490: if (recursive) {
491: resources = cms.readResources(resourceRootPath,
492: CmsResourceFilter.IGNORE_EXPIRATION);
493: } else {
494: resources.add(resourceRootPath);
495: }
496:
497: List changedResources = new ArrayList(resources.size());
498: CmsProperty newProperty = new CmsProperty(propertyDefinition,
499: null, null);
500: // create permission set and filter to check each resource
501: for (int i = 0; i < resources.size(); i++) {
502: // loop through found resources and check property values
503: CmsResource res = (CmsResource) resources.get(i);
504: CmsProperty property = cms.readPropertyObject(res,
505: propertyDefinition, false);
506: if (property.isNullProperty()) {
507: // change structure value
508: newProperty.setStructureValue(newValue);
509: newProperty.setName(propertyDefinition);
510: cms
511: .writePropertyObject(cms.getRequestContext()
512: .removeSiteRoot(res.getRootPath()),
513: newProperty);
514: changedResources.add(res);
515: } else {
516: // nop
517: }
518: }
519: return changedResources;
520: }
521:
522: /**
523: * Sets the changed resources that were affected by the property change action.<p>
524: *
525: * @param changedResources the changed resources that were affected by the property change action
526: */
527: private void setChangedResources(List changedResources) {
528:
529: m_changedResources = changedResources;
530: }
531:
532: /**
533: * Validates the submitted form parameters.<p>
534: *
535: * If parameters are missing, a localized error message String is created.<p>
536: *
537: * @return true if all parameters are correct, otherwise false
538: *
539: */
540: private boolean validateParameters() {
541:
542: boolean allOk = true;
543:
544: StringBuffer validationErrors = new StringBuffer(32);
545: CmsMessages messages = Messages.get().getBundle(getLocale());
546:
547: // check resource parameter presence
548: if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamResource())
549: || !getCms().existsResource(getParamResource())) {
550: allOk = false;
551: validationErrors
552: .append(
553: messages
554: .key(Messages.GUI_PROP_CHANGE_VALIDATE_VFS_RESOURCE_0))
555: .append("<br>");
556: }
557:
558: // check selected property name
559: if (CmsStringUtil
560: .isEmptyOrWhitespaceOnly(getParamPropertyName())) {
561: allOk = false;
562: validationErrors
563: .append(
564: messages
565: .key(Messages.GUI_PROP_CHANGE_VALIDATE_SELECT_PROPERTY_0))
566: .append("<br>");
567: }
568:
569: // check old property value to look up
570: if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamOldValue())) {
571: allOk = false;
572: validationErrors
573: .append(
574: messages
575: .key(Messages.GUI_PROP_CHANGE_VALIDATE_OLD_PROP_VALUE_0))
576: .append("<br>");
577: } else {
578: try {
579: // compile regular expression pattern
580: Pattern.compile(getParamOldValue());
581: } catch (PatternSyntaxException e) {
582: allOk = false;
583: validationErrors
584: .append(
585: messages
586: .key(Messages.GUI_PROP_CHANGE_VALIDATE_OLD_PROP_PATTERN_0))
587: .append("<br>");
588: }
589: }
590:
591: // check new property value
592: if (CmsStringUtil.isEmptyOrWhitespaceOnly(getParamNewValue())) {
593: // if no new value was given, set it to the delete value
594: setParamNewValue(CmsProperty.DELETE_VALUE);
595: }
596:
597: setErrorMessage(validationErrors.toString());
598: setValidationErrors(!allOk);
599: return allOk;
600: }
601: }
|