001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/workplace/commons/CmsCopy.java,v $
003: * Date : $Date: 2008-02-27 12:05:25 $
004: * Version: $Revision: 1.26 $
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.commons;
033:
034: import org.opencms.file.CmsResource;
035: import org.opencms.file.CmsResourceFilter;
036: import org.opencms.file.CmsVfsException;
037: import org.opencms.file.CmsVfsResourceAlreadyExistsException;
038: import org.opencms.file.CmsVfsResourceNotFoundException;
039: import org.opencms.file.CmsResource.CmsResourceCopyMode;
040: import org.opencms.jsp.CmsJspActionElement;
041: import org.opencms.lock.CmsLockException;
042: import org.opencms.main.CmsException;
043: import org.opencms.main.CmsLog;
044: import org.opencms.main.OpenCms;
045: import org.opencms.security.CmsPermissionSet;
046: import org.opencms.staticexport.CmsLinkManager;
047: import org.opencms.util.CmsStringUtil;
048: import org.opencms.workplace.CmsMultiDialog;
049: import org.opencms.workplace.CmsWorkplaceSettings;
050:
051: import java.util.ArrayList;
052: import java.util.Iterator;
053: import java.util.List;
054:
055: import javax.servlet.http.HttpServletRequest;
056: import javax.servlet.http.HttpServletResponse;
057: import javax.servlet.jsp.JspException;
058: import javax.servlet.jsp.PageContext;
059:
060: import org.apache.commons.logging.Log;
061:
062: /**
063: * Provides methods for the copy resources dialog.<p>
064: *
065: * The following files use this class:
066: * <ul>
067: * <li>/commons/copy.jsp
068: * </ul>
069: * <p>
070: *
071: * @author Andreas Zahner
072: *
073: * @version $Revision: 1.26 $
074: *
075: * @since 6.0.0
076: */
077: public class CmsCopy extends CmsMultiDialog {
078:
079: /** Value for the action: copy the resource. */
080: public static final int ACTION_COPY = 100;
081:
082: /** The dialog type. */
083: public static final String DIALOG_TYPE = "copy";
084:
085: /** Request parameter name for the keep rights flag. */
086: public static final String PARAM_KEEPRIGHTS = "keeprights";
087:
088: /** Request parameter name for the overwrite flag. */
089: public static final String PARAM_OVERWRITE = "overwrite";
090:
091: /** The log object for this class. */
092: private static final Log LOG = CmsLog.getLog(CmsCopy.class);
093:
094: private String m_paramCopymode;
095: private String m_paramKeeprights;
096: private String m_paramOverwrite;
097: private String m_paramTarget;
098:
099: /**
100: * Public constructor with JSP action element.<p>
101: *
102: * @param jsp an initialized JSP action element
103: */
104: public CmsCopy(CmsJspActionElement jsp) {
105:
106: super (jsp);
107: }
108:
109: /**
110: * Public constructor with JSP variables.<p>
111: *
112: * @param context the JSP page context
113: * @param req the JSP request
114: * @param res the JSP response
115: */
116: public CmsCopy(PageContext context, HttpServletRequest req,
117: HttpServletResponse res) {
118:
119: this (new CmsJspActionElement(context, req, res));
120: }
121:
122: /**
123: * Performs the copy action, will be called by the JSP page.<p>
124: *
125: * @throws JspException if problems including sub-elements occur
126: */
127: public void actionCopy() throws JspException {
128:
129: // save initialized instance of this class in request attribute for included sub-elements
130: getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS,
131: this );
132: CmsResource resource = null;
133: try {
134: boolean isFolder = false;
135: String source = (String) getResourceList().get(0);
136: String target = CmsLinkManager.getAbsoluteUri(
137: getParamTarget(), CmsResource
138: .getParentFolder(source));
139: if (!isMultiOperation()) {
140: resource = getCms().readResource(source,
141: CmsResourceFilter.ALL);
142: isFolder = resource.isFolder();
143: } else {
144: String siteRootFolder = null;
145: try {
146: // check if a site root was added to the target name
147: if (OpenCms.getSiteManager().getSiteRoot(target) != null) {
148: siteRootFolder = getCms().getRequestContext()
149: .getSiteRoot();
150: if (siteRootFolder.endsWith("/")) {
151: siteRootFolder = siteRootFolder.substring(
152: 0, siteRootFolder.length() - 1);
153: }
154: getCms().getRequestContext().setSiteRoot("/");
155: }
156: resource = getCms().readResource(target,
157: CmsResourceFilter.ALL);
158: } finally {
159: if (siteRootFolder != null) {
160: getCms().getRequestContext().setSiteRoot(
161: siteRootFolder);
162: }
163: }
164: if (!resource.isFolder()) {
165: // no folder selected for multi operation, throw exception
166: throw new CmsVfsException(Messages.get().container(
167: Messages.ERR_COPY_MULTI_TARGET_NOFOLDER_1,
168: target));
169: }
170: }
171: if (performDialogOperation()) {
172: // if no exception is caused and "true" is returned copy operation was successful
173: if (isMultiOperation() || isFolder) {
174: // set request attribute to reload the explorer tree view
175: List folderList = new ArrayList(1);
176: String targetParent = CmsResource
177: .getParentFolder(target);
178: folderList.add(targetParent);
179: getJsp().getRequest().setAttribute(
180: REQUEST_ATTRIBUTE_RELOADTREE, folderList);
181: }
182: actionCloseDialog();
183: } else {
184: // "false" returned, display "please wait" screen
185: getJsp().include(FILE_DIALOG_SCREEN_WAIT);
186: }
187: } catch (Throwable e) {
188: // check if this exception requires a confirmation or error screen for single resource operations
189: if (!isMultiOperation()
190: && ((e instanceof CmsVfsResourceAlreadyExistsException) || (e instanceof CmsLockException))
191: && (resource != null) && !(resource.isFolder())) {
192: // file copy but file already exists, now check target file type
193: int targetType = -1;
194: String storedSiteRoot = null;
195: try {
196: if (OpenCms.getSiteManager().getSiteRoot(
197: getParamTarget()) != null) {
198: storedSiteRoot = getCms().getRequestContext()
199: .getSiteRoot();
200: getCms().getRequestContext().setSiteRoot("/");
201: }
202: CmsResource targetRes = getCms().readResource(
203: getParamTarget());
204: targetType = targetRes.getTypeId();
205: } catch (CmsException e2) {
206: // can usually be ignored
207: if (LOG.isInfoEnabled()) {
208: LOG.info(e2.getLocalizedMessage());
209: }
210: } finally {
211: if (storedSiteRoot != null) {
212: getCms().getRequestContext().setSiteRoot(
213: storedSiteRoot);
214: }
215: }
216: if (resource.getTypeId() == targetType) {
217: // file type of target is the same as source, show confirmation dialog
218: setParamMessage(CmsStringUtil.escapeHtml(key(
219: Messages.GUI_COPY_CONFIRM_OVERWRITE_2,
220: new Object[] { getParamResource(),
221: getParamTarget() })));
222: getJsp().include(FILE_DIALOG_SCREEN_CONFIRM);
223: } else {
224: // file type is different, create error message
225: includeErrorpage(this , e);
226: }
227: } else {
228: // error during copy, show error dialog
229: includeErrorpage(this , e);
230: }
231: }
232: }
233:
234: /**
235: * Builds the input radio buttons to select between preserving links or creating new resources when copying.<p>
236: *
237: * @return the HTML code for the radio buttons
238: */
239: public String buildRadioCopyMode() {
240:
241: StringBuffer retValue = new StringBuffer(256);
242:
243: // check if the current resource is a folder for single operation
244: boolean isFolder = isOperationOnFolder();
245: String checkedAttr = " checked=\"checked\"";
246:
247: if (isMultiOperation() || isFolder) {
248: // for multi resource operations or folders, show an additional option "preserve links"
249: CmsResourceCopyMode defaultMode = getSettings()
250: .getUserSettings().getDialogCopyFolderMode();
251: retValue
252: .append("<input type=\"radio\" name=\"copymode\" value=\"");
253: retValue.append(CmsResource.COPY_AS_SIBLING.getMode());
254: retValue.append("\"");
255: if (defaultMode == CmsResource.COPY_AS_SIBLING) {
256: retValue.append(checkedAttr);
257: }
258: retValue.append("> ");
259: String msgKey;
260: if (isMultiOperation()) {
261: msgKey = Messages.GUI_COPY_MULTI_CREATE_SIBLINGS_0;
262: } else {
263: msgKey = Messages.GUI_COPY_CREATE_SIBLINGS_0;
264: }
265: retValue.append(key(msgKey));
266: retValue.append("<br>\n");
267: retValue
268: .append("<input type=\"radio\" name=\"copymode\" value=\"");
269: retValue
270: .append(CmsResource.COPY_PRESERVE_SIBLING.getMode());
271: retValue.append("\"");
272: if (defaultMode == CmsResource.COPY_PRESERVE_SIBLING) {
273: retValue.append(checkedAttr);
274: }
275: retValue.append("> ");
276: retValue.append(key(Messages.GUI_COPY_ALL_NO_SIBLINGS_0));
277: retValue.append("<br>\n");
278: retValue
279: .append("<input type=\"radio\" name=\"copymode\" value=\"");
280: retValue.append(CmsResource.COPY_AS_NEW.getMode());
281: retValue.append("\"");
282: if (defaultMode == CmsResource.COPY_AS_NEW) {
283: retValue.append(checkedAttr);
284: }
285: retValue.append("> ");
286: retValue.append(key(Messages.GUI_COPY_ALL_0));
287: retValue.append("<br>\n");
288:
289: if (isMultiOperation()) {
290: // show overwrite option for multi resource copy
291: retValue.append(dialogSpacer());
292: retValue.append("<input type=\"checkbox\" name=\"");
293: retValue.append(PARAM_OVERWRITE);
294: retValue.append("\" value=\"true\"> ");
295: retValue
296: .append(key(Messages.GUI_COPY_MULTI_OVERWRITE_0));
297: retValue.append("<br>\n");
298: }
299: } else {
300: // for files, show copy option "copy as sibling" and "copy as new resource"
301: CmsResourceCopyMode defaultMode = getSettings()
302: .getUserSettings().getDialogCopyFileMode();
303: retValue
304: .append("<input type=\"radio\" name=\"copymode\" value=\"");
305: retValue.append(CmsResource.COPY_AS_SIBLING.getMode());
306: retValue.append("\"");
307: if (defaultMode == CmsResource.COPY_AS_SIBLING) {
308: retValue.append(checkedAttr);
309: }
310: retValue.append("> ");
311: retValue.append(key(Messages.GUI_CREATE_SIBLING_0));
312: retValue.append("<br>\n");
313: retValue
314: .append("<input type=\"radio\" name=\"copymode\" value=\"");
315: retValue.append(CmsResource.COPY_AS_NEW.getMode());
316: retValue.append("\"");
317: if (defaultMode == CmsResource.COPY_AS_NEW) {
318: retValue.append(checkedAttr);
319: }
320: retValue.append("> ");
321: retValue.append(key(Messages.GUI_COPY_AS_NEW_0));
322: retValue.append("<br>\n");
323: }
324:
325: return retValue.toString();
326: }
327:
328: /**
329: * Returns the value of the copymode parameter.<p>
330: *
331: * @return the value of the copymode parameter
332: */
333: public String getParamCopymode() {
334:
335: return m_paramCopymode;
336: }
337:
338: /**
339: * Returns the value of the keeprights parameter.<p>
340: *
341: * @return the value of the keeprights parameter
342: */
343: public String getParamKeeprights() {
344:
345: return m_paramKeeprights;
346: }
347:
348: /**
349: * Returns the value of the overwrite parameter.<p>
350: *
351: * @return the value of the overwrite parameter
352: */
353: public String getParamOverwrite() {
354:
355: return m_paramOverwrite;
356: }
357:
358: /**
359: * Returns the value of the target parameter,
360: * or null if this parameter was not provided.<p>
361: *
362: * The target parameter selects the target name
363: * of the operation.<p>
364: *
365: * @return the value of the target parameter
366: */
367: public String getParamTarget() {
368:
369: return m_paramTarget;
370: }
371:
372: /**
373: * Sets the value of the copymode parameter.<p>
374: *
375: * @param value the value of the copymode parameter
376: */
377: public void setParamCopymode(String value) {
378:
379: m_paramCopymode = value;
380: }
381:
382: /**
383: * Sets the value of the "keeprights" parameter.<p>
384: *
385: * @param value the value of the "keeprights" parameter
386: */
387: public void setParamKeeprights(String value) {
388:
389: m_paramKeeprights = value;
390: }
391:
392: /**
393: * Sets the value of the overwrite parameter.<p>
394: *
395: * @param paramOverwrite the value of the overwrite parameter
396: */
397: public void setParamOverwrite(String paramOverwrite) {
398:
399: m_paramOverwrite = paramOverwrite;
400: }
401:
402: /**
403: * Sets the value of the target parameter.<p>
404: *
405: * @param value the value to set
406: */
407: public void setParamTarget(String value) {
408:
409: m_paramTarget = value;
410: }
411:
412: /**
413: * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
414: */
415: protected void initWorkplaceRequestValues(
416: CmsWorkplaceSettings settings, HttpServletRequest request) {
417:
418: // fill the parameter values in the get/set methods
419: fillParamValues(request);
420:
421: // check the required permissions to copy the resource
422: if (!checkResourcePermissions(CmsPermissionSet.ACCESS_WRITE,
423: false)) {
424: // no write permissions for the resource, set cancel action to close dialog
425: setParamAction(DIALOG_CANCEL);
426: }
427:
428: // set the dialog type
429: setParamDialogtype(DIALOG_TYPE);
430: // set the action for the JSP switch
431: if (DIALOG_TYPE.equals(getParamAction())) {
432: setAction(ACTION_COPY);
433: } else if (DIALOG_CONFIRMED.equals(getParamAction())) {
434: setAction(ACTION_CONFIRMED);
435: } else if (DIALOG_WAIT.equals(getParamAction())) {
436: setAction(ACTION_WAIT);
437: } else if (DIALOG_CANCEL.equals(getParamAction())) {
438: setAction(ACTION_CANCEL);
439: } else {
440: setAction(ACTION_DEFAULT);
441: // build title for copy dialog
442: setDialogTitle(Messages.GUI_COPY_RESOURCE_1,
443: Messages.GUI_COPY_MULTI_2);
444: }
445: }
446:
447: /**
448: * Performs the resource copying.<p>
449: *
450: * @return true, if the resource was copied, otherwise false
451: * @throws CmsException if copying is not successful
452: */
453: protected boolean performDialogOperation() throws CmsException {
454:
455: // check if the current resource is a folder for single operation
456: boolean isFolder = isOperationOnFolder();
457:
458: // on folder copy display "please wait" screen, not for simple file copy
459: if ((isMultiOperation() || isFolder)
460: && !DIALOG_WAIT.equals(getParamAction())) {
461: // return false, this will trigger the "please wait" screen
462: return false;
463: }
464:
465: // get the copy mode from request parameter value
466: CmsResourceCopyMode copyMode = CmsResource.COPY_PRESERVE_SIBLING;
467: try {
468: copyMode = CmsResourceCopyMode.valueOf(Integer
469: .parseInt(getParamCopymode()));
470: } catch (Exception e) {
471: // can usually be ignored
472: if (LOG.isInfoEnabled()) {
473: LOG.info(e.getLocalizedMessage());
474: }
475: }
476:
477: // check the overwrite options
478: boolean overwrite = Boolean.valueOf(getParamOverwrite())
479: .booleanValue();
480: overwrite = ((isMultiOperation() && overwrite) || DIALOG_CONFIRMED
481: .equals(getParamAction()));
482:
483: // calculate the target name
484: String target = getParamTarget();
485: if (target == null) {
486: target = "";
487: }
488:
489: String storedSiteRoot = null;
490: try {
491: // check if a site root was added to the target name
492: String sitePrefix = "";
493: if (OpenCms.getSiteManager().getSiteRoot(target) != null) {
494: String siteRootFolder = getCms().getRequestContext()
495: .getSiteRoot();
496: if (siteRootFolder.endsWith("/")) {
497: siteRootFolder = siteRootFolder.substring(0,
498: siteRootFolder.length() - 1);
499: }
500: sitePrefix = siteRootFolder;
501: storedSiteRoot = getCms().getRequestContext()
502: .getSiteRoot();
503: getCms().getRequestContext().setSiteRoot("/");
504: }
505:
506: Iterator i = getResourceList().iterator();
507: // iterate the resources to copy
508: while (i.hasNext()) {
509: String resName = (String) i.next();
510: try {
511: performSingleCopyOperation(resName, target,
512: sitePrefix, copyMode, overwrite);
513: } catch (CmsException e) {
514: if (isMultiOperation()) {
515: // collect exceptions to create a detailed output
516: addMultiOperationException(e);
517: } else {
518: // for single operation, throw the exception immediately
519: throw e;
520: }
521: }
522: }
523: // check if exceptions occurred
524: checkMultiOperationException(Messages.get(),
525: Messages.ERR_COPY_MULTI_0);
526: } finally {
527: // restore the site root
528: if (storedSiteRoot != null) {
529: getCms().getRequestContext()
530: .setSiteRoot(storedSiteRoot);
531: }
532: }
533: return true;
534: }
535:
536: /**
537: * Performs the copy operation for a single VFS resource.<p>
538: *
539: * @param source the source VFS path
540: * @param target the target VFS path
541: * @param sitePrefix the site prefix
542: * @param copyMode the copy mode for siblings
543: * @param overwrite the overwrite flag
544: *
545: * @throws CmsException if copying the resource fails
546: */
547: protected void performSingleCopyOperation(String source,
548: String target, String sitePrefix,
549: CmsResourceCopyMode copyMode, boolean overwrite)
550: throws CmsException {
551:
552: // calculate the target name
553: String finalTarget = CmsLinkManager.getAbsoluteUri(target,
554: CmsResource.getParentFolder(source));
555:
556: if (finalTarget.equals(source)
557: || (isMultiOperation() && finalTarget
558: .startsWith(source))) {
559: throw new CmsVfsException(Messages.get().container(
560: Messages.ERR_COPY_ONTO_ITSELF_1, finalTarget));
561: }
562:
563: try {
564: CmsResource res = getCms().readResource(finalTarget,
565: CmsResourceFilter.ALL);
566: if (res.isFolder()) {
567: // target folder already exists, so we add the current folder name
568: if (!finalTarget.endsWith("/")) {
569: finalTarget += "/";
570: }
571: finalTarget = finalTarget + CmsResource.getName(source);
572: }
573: } catch (CmsVfsResourceNotFoundException e) {
574: // target folder does not already exist, so target name is o.k.
575: if (LOG.isInfoEnabled()) {
576: LOG.info(e.getLocalizedMessage());
577: }
578: }
579:
580: // set the target parameter value
581: setParamTarget(finalTarget);
582:
583: // delete existing target resource if selected or confirmed by the user
584: if (overwrite && getCms().existsResource(finalTarget)) {
585: checkLock(finalTarget);
586: getCms().deleteResource(finalTarget,
587: CmsResource.DELETE_PRESERVE_SIBLINGS);
588: }
589: // copy the resource
590: getCms().copyResource(sitePrefix + source, finalTarget,
591: copyMode);
592: }
593: }
|