001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.ui.dialogs; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResource.CmsResourceCopyMode; 033import org.opencms.file.CmsResourceFilter; 034import org.opencms.file.CmsVfsException; 035import org.opencms.file.types.CmsResourceTypeFolderSubSitemap; 036import org.opencms.file.types.CmsResourceTypeXmlContainerPage; 037import org.opencms.i18n.tools.CmsContainerPageCopier; 038import org.opencms.i18n.tools.CmsContainerPageCopier.NoCustomReplacementException; 039import org.opencms.lock.CmsLockActionRecord; 040import org.opencms.lock.CmsLockUtil; 041import org.opencms.main.CmsException; 042import org.opencms.main.CmsIllegalArgumentException; 043import org.opencms.main.CmsLog; 044import org.opencms.main.OpenCms; 045import org.opencms.security.CmsSecurityException; 046import org.opencms.staticexport.CmsLinkManager; 047import org.opencms.ui.A_CmsUI; 048import org.opencms.ui.CmsVaadinUtils; 049import org.opencms.ui.I_CmsDialogContext; 050import org.opencms.ui.apps.sitemanager.CmsSiteManager; 051import org.opencms.ui.components.CmsBasicDialog; 052import org.opencms.ui.components.CmsConfirmationDialog; 053import org.opencms.ui.components.CmsErrorDialog; 054import org.opencms.ui.components.CmsMacroResolverDialog; 055import org.opencms.ui.components.CmsOkCancelActionHandler; 056import org.opencms.ui.components.fileselect.CmsPathSelectField; 057import org.opencms.util.CmsMacroResolver; 058import org.opencms.util.CmsStringUtil; 059import org.opencms.util.CmsUUID; 060 061import java.util.ArrayList; 062import java.util.Arrays; 063import java.util.Collections; 064import java.util.HashMap; 065import java.util.HashSet; 066import java.util.List; 067import java.util.Map; 068import java.util.Set; 069 070import org.apache.commons.logging.Log; 071 072import com.vaadin.ui.Button; 073import com.vaadin.ui.Button.ClickEvent; 074import com.vaadin.ui.Button.ClickListener; 075import com.vaadin.ui.FormLayout; 076import com.vaadin.ui.UI; 077import com.vaadin.ui.Window; 078import com.vaadin.v7.ui.CheckBox; 079import com.vaadin.v7.ui.ComboBox; 080import com.vaadin.v7.ui.ComboBox.ItemStyleGenerator; 081 082/** 083 * The copy move dialog.<p> 084 */ 085@SuppressWarnings("deprecation") 086public class CmsCopyMoveDialog extends CmsBasicDialog { 087 088 /** The copy/move actions. */ 089 public static enum Action { 090 091 /** Copy container page automatic mode. */ 092 container_page_automatic, 093 /** Copy container page including referenced elements. */ 094 container_page_copy, 095 /** Copy container page reuse referenced elements. */ 096 container_page_reuse, 097 /** Copy resources as new. */ 098 copy_all, 099 /** Create siblings. */ 100 copy_sibling_all, 101 /** Copy and preserve siblings. */ 102 copy_sibling_mixed, 103 /** Move resources. */ 104 move, 105 /** Copy sub sitemap, adjust internal links. */ 106 sub_sitemap; 107 } 108 109 /** The dialog mode. */ 110 public static enum DialogMode { 111 /** Allow copy only. */ 112 copy, 113 /** Allow copy and move. */ 114 copy_and_move, 115 /** Allow move only. */ 116 move 117 } 118 119 /** Logger instance for this class. */ 120 static final Log LOG = CmsLog.getLog(CmsCopyMoveDialog.class); 121 122 /** The serial version id. */ 123 private static final long serialVersionUID = 1L; 124 125 /** The default actions. */ 126 List<Action> m_defaultActions; 127 128 /** The action radio buttons. */ 129 private ComboBox m_actionCombo; 130 131 /** The cancel button. */ 132 private Button m_cancelButton; 133 134 /** The cms context. */ 135 private CmsObject m_cms; 136 137 /** The dialog context. */ 138 private I_CmsDialogContext m_context; 139 140 /** Flag indicating the move option is allowed. */ 141 private DialogMode m_dialogMode; 142 143 /** Indicates the copy folder has a default file of the type container page. */ 144 private boolean m_hasContainerPageDefaultFile; 145 146 /**Dialog for editing key value pairs used as macros. Only used for sitemap folder*/ 147 private CmsMacroResolverDialog m_macroDialog; 148 149 /** The OK button. */ 150 private Button m_okButton; 151 152 /** The overwrite existing resources checkbox. */ 153 private CheckBox m_overwriteExisting; 154 155 /** The root cms context. */ 156 private CmsObject m_rootCms; 157 158 /** The target path select field. */ 159 private CmsPathSelectField m_targetPath; 160 161 /** The resources to update after dialog close. */ 162 private Set<CmsUUID> m_updateResources; 163 164 /** 165 * Constructor.<p> 166 * 167 * @param context the dialog context 168 * @param mode the dialog mode 169 */ 170 public CmsCopyMoveDialog(final I_CmsDialogContext context, DialogMode mode) { 171 172 m_dialogMode = mode; 173 m_updateResources = new HashSet<CmsUUID>(); 174 m_context = context; 175 m_defaultActions = new ArrayList<Action>(); 176 displayResourceInfo(context.getResources()); 177 FormLayout form = initForm(); 178 setContent(form); 179 updateDefaultActions(null); 180 m_okButton = new Button(CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_OK_0)); 181 m_okButton.addClickListener(new ClickListener() { 182 183 private static final long serialVersionUID = 1L; 184 185 public void buttonClick(ClickEvent event) { 186 187 submit(false, null); 188 } 189 }); 190 addButton(m_okButton); 191 m_cancelButton = new Button( 192 CmsVaadinUtils.getMessageText(org.opencms.workplace.Messages.GUI_DIALOG_BUTTON_CANCEL_0)); 193 m_cancelButton.addClickListener(new ClickListener() { 194 195 private static final long serialVersionUID = 1L; 196 197 public void buttonClick(ClickEvent event) { 198 199 cancel(); 200 } 201 }); 202 addButton(m_cancelButton); 203 setActionHandler(new CmsOkCancelActionHandler() { 204 205 private static final long serialVersionUID = 1L; 206 207 @Override 208 protected void cancel() { 209 210 CmsCopyMoveDialog.this.cancel(); 211 } 212 213 @Override 214 protected void ok() { 215 216 submit(false, null); 217 } 218 }); 219 } 220 221 /** 222 * Preselects the target folder.<p> 223 * 224 * @param structureId the target structure id 225 * 226 * @throws CmsException in case the target can not be read or is not a folder 227 */ 228 public void setTargetFolder(CmsUUID structureId) throws CmsException { 229 230 CmsObject cms = A_CmsUI.getCmsObject(); 231 CmsResource res = cms.readResource(structureId); 232 setTargetForlder(res); 233 } 234 235 /** 236 * Preselects the target folder.<p> 237 * 238 * @param resource the target resource 239 */ 240 public void setTargetForlder(CmsResource resource) { 241 242 if (resource.isFolder()) { 243 if (m_context.getResources().size() == 1) { 244 try { 245 if (m_dialogMode.equals(DialogMode.copy) 246 | (m_dialogMode.equals(DialogMode.copy_and_move) 247 && CmsResource.getParentFolder(m_context.getResources().get(0).getRootPath()).equals( 248 resource.getRootPath()))) { 249 m_targetPath.setValue(getTargetName(m_context.getResources().get(0), resource)); 250 } else { 251 252 m_targetPath.setValue( 253 getCms().getSitePath(resource) + getTargetName(m_context.getResources().get(0), resource)); 254 } 255 } catch (CmsException e) { 256 m_targetPath.setValue(getCms().getSitePath(resource)); 257 } 258 } else { 259 m_targetPath.setValue(getCms().getSitePath(resource)); 260 } 261 262 updateDefaultActions(resource.getRootPath()); 263 } else { 264 throw new CmsIllegalArgumentException( 265 org.opencms.workplace.commons.Messages.get().container( 266 org.opencms.workplace.commons.Messages.ERR_COPY_MULTI_TARGET_NOFOLDER_1, 267 A_CmsUI.getCmsObject().getSitePath(resource))); 268 } 269 } 270 271 /** 272 * Get bunle values from dialog.<p> 273 * 274 * @return map of key-value pairs to be resolved as macro. if null or empty, then ignored 275 */ 276 protected Map<String, String> getMacroMap() { 277 278 return m_macroDialog.getMacroMap(); 279 } 280 281 /** 282 * Performs the single resource operation.<p> 283 * 284 * @param source the source 285 * @param target the target 286 * @param action the action 287 * @param overwrite if existing resources should be overwritten 288 * @param makroMap map of key-value pairs to be resolved as macro. if null or empty, then ignored 289 * 290 * @throws CmsException in case the operation fails 291 */ 292 protected void performSingleOperation( 293 CmsResource source, 294 CmsResource target, 295 Action action, 296 boolean overwrite, 297 Map<String, String> makroMap) 298 throws CmsException { 299 300 performSingleOperation(source, target, getTargetName(source, target), action, overwrite, makroMap); 301 } 302 303 /** 304 * Performs the single resource operation.<p> 305 * 306 * @param source the source 307 * @param target the target folder 308 * @param name the target resource name 309 * @param action the action 310 * @param overwrite if existing resources should be overwritten 311 * @param macroMap map of key-value pairs to be resolved as macro. if null or empty, then ignored 312 * 313 * @throws CmsException in case the operation fails 314 */ 315 protected void performSingleOperation( 316 CmsResource source, 317 CmsResource target, 318 String name, 319 Action action, 320 boolean overwrite, 321 Map<String, String> macroMap) 322 throws CmsException { 323 324 // add new parent and source to the update resources 325 m_updateResources.add(target.getStructureId()); 326 m_updateResources.add(source.getStructureId()); 327 328 String finalTarget = target.getRootPath(); 329 if (finalTarget.equals(source.getRootPath()) || finalTarget.startsWith(source.getRootPath())) { 330 throw new CmsVfsException( 331 org.opencms.workplace.commons.Messages.get().container( 332 org.opencms.workplace.commons.Messages.ERR_COPY_ONTO_ITSELF_1, 333 finalTarget)); 334 } 335 finalTarget = CmsStringUtil.joinPaths(finalTarget, name); 336 // delete existing target resource if selected or confirmed by the user 337 if (overwrite && getRootCms().existsResource(finalTarget, CmsResourceFilter.ONLY_VISIBLE)) { 338 CmsLockUtil.ensureLock( 339 getRootCms(), 340 getRootCms().readResource(finalTarget, CmsResourceFilter.ONLY_VISIBLE)); 341 if (getRootCms().existsResource(finalTarget, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED)) { 342 if ((action != Action.container_page_automatic) 343 && (action != Action.container_page_copy) 344 && (action != Action.container_page_reuse)) { 345 // container page copy modes don't just call copyResource(), they need special handling for the overwrite case 346 getRootCms().deleteResource(finalTarget, CmsResource.DELETE_PRESERVE_SIBLINGS); 347 } 348 } 349 } 350 // copy the resource 351 if (action == Action.move) { 352 // add former parent to the update resources 353 CmsResource parent = getRootCms().readParentFolder(source.getStructureId()); 354 m_updateResources.add(parent.getStructureId()); 355 CmsLockActionRecord lockRecord = CmsLockUtil.ensureLock(getRootCms(), source); 356 getRootCms().moveResource(source.getRootPath(), finalTarget); 357 if (lockRecord.getChange() == CmsLockActionRecord.LockChange.locked) { 358 getRootCms().unlockResource(finalTarget); 359 } 360 } else if ((action == Action.container_page_automatic) 361 || (action == Action.container_page_copy) 362 || (action == Action.container_page_reuse)) { 363 CmsContainerPageCopier copier = new CmsContainerPageCopier(m_context.getCms()); 364 try { 365 366 CmsContainerPageCopier.CopyMode mode = action == Action.container_page_automatic 367 ? CmsContainerPageCopier.CopyMode.automatic 368 : (action == Action.container_page_copy 369 ? CmsContainerPageCopier.CopyMode.smartCopyAndChangeLocale 370 : CmsContainerPageCopier.CopyMode.reuse); 371 copier.setCopyMode(mode); 372 copier.run(m_context.getResources().get(0), target, name); 373 m_context.finish( 374 Arrays.asList( 375 copier.getTargetFolder().getStructureId(), 376 copier.getCopiedFolderOrPage().getStructureId())); 377 } catch (CmsException e) { 378 m_context.error(e); 379 } catch (NoCustomReplacementException e) { 380 String errorMessage = CmsVaadinUtils.getMessageText( 381 org.opencms.ui.Messages.GUI_COPYPAGE_NO_REPLACEMENT_FOUND_1, 382 e.getResource().getRootPath()); 383 CmsErrorDialog.showErrorDialog(errorMessage, e); 384 } 385 } else { 386 387 CmsResourceCopyMode copyMode = null; 388 switch ((Action)m_actionCombo.getValue()) { 389 case copy_all: 390 copyMode = CmsResource.COPY_AS_NEW; 391 break; 392 case copy_sibling_all: 393 copyMode = CmsResource.COPY_AS_SIBLING; 394 break; 395 case copy_sibling_mixed: 396 case sub_sitemap: 397 default: 398 copyMode = CmsResource.COPY_PRESERVE_SIBLING; 399 } 400 401 //Copies resources. Adjust links if action==Action.sub_sitemap, resolves macro if marcoMap if not null or empty 402 CmsMacroResolver.copyAndResolveMacro( 403 getRootCms(), 404 source.getRootPath(), 405 finalTarget, 406 macroMap, 407 action == Action.sub_sitemap, 408 copyMode); 409 410 getRootCms().unlockResource(finalTarget); 411 412 CmsResource copyResource = getRootCms().readResource(finalTarget, CmsResourceFilter.IGNORE_EXPIRATION); 413 m_updateResources.add(copyResource.getStructureId()); 414 } 415 } 416 417 /** 418 * Updates the 'overwrite existing' checkbox state depending on the currently selected mode.<p> 419 */ 420 protected void updateOverwriteExisting() { 421 422 if (m_overwriteExisting != null) { 423 boolean move = (m_dialogMode == DialogMode.move) || (m_actionCombo.getValue() == Action.move); 424 if (move) { 425 m_overwriteExisting.setValue(Boolean.FALSE); 426 m_overwriteExisting.setVisible(false); 427 } else { 428 m_overwriteExisting.setVisible(true); 429 } 430 } 431 } 432 433 /** 434 * Cancels the dialog action.<p> 435 */ 436 void cancel() { 437 438 m_context.finish(Collections.<CmsUUID> emptyList()); 439 } 440 441 /** 442 * Submits the dialog action.<p> 443 * 444 * @param overwrite to forcefully overwrite existing files 445 * @param makroMap map of key-value pairs to be resolved as macro. if null or empty, then ignored 446 */ 447 void submit(boolean overwrite, Map<String, String> makroMap) { 448 449 try { 450 CmsResource targetFolder = null; 451 String targetName = null; 452 String target = m_targetPath.getValue(); 453 boolean isSingleResource = m_context.getResources().size() == 1; 454 // resolve relative paths 455 target = CmsLinkManager.getAbsoluteUri( 456 target, 457 CmsResource.getParentFolder(getCms().getSitePath(m_context.getResources().get(0)))); 458 459 // check if the given path is a root path 460 CmsObject cms = OpenCms.getSiteManager().getSiteForRootPath(target) != null ? getRootCms() : getCms(); 461 462 if (cms.existsResource(target, CmsResourceFilter.ALL.addRequireFolder())) { 463 // The target is an existing folder 464 // always copy files into that folder 465 targetFolder = cms.readResource(target); 466 } else if (cms.existsResource(target, CmsResourceFilter.ALL.addRequireFile())) { 467 // The target is an existing file 468 if (isSingleResource) { 469 // Replace the file with the resource copied, if it is just a single resource 470 if (target.equals(m_context.getResources().get(0).getRootPath())) { 471 throw new CmsVfsException( 472 org.opencms.workplace.commons.Messages.get().container( 473 org.opencms.workplace.commons.Messages.ERR_COPY_ONTO_ITSELF_1, 474 target)); 475 } 476 targetName = CmsResource.getName(target); 477 targetFolder = cms.readResource(CmsResource.getParentFolder(target)); 478 } else { 479 // Throw an error if a single file should be replaced with multiple resources 480 // since we cannot copy multiple resources to a single file 481 throw new CmsVfsException( 482 org.opencms.workplace.commons.Messages.get().container( 483 org.opencms.workplace.commons.Messages.ERR_COPY_MULTI_TARGET_NOFOLDER_1, 484 target)); 485 } 486 } else { 487 // The target does not exist 488 if (isSingleResource) { 489 // If we have a single resource, we could possible create the target as copy of that resource 490 if (cms.existsResource( 491 CmsResource.getParentFolder(target), 492 CmsResourceFilter.ALL.addRequireFolder())) { 493 targetName = CmsResource.getName(target); 494 targetFolder = cms.readResource(CmsResource.getParentFolder(target)); 495 } else { 496 // If the parent folder of the resource does not exist, we will not create it automatically. 497 // Thus we need to throw an exception. 498 throw new CmsVfsException( 499 org.opencms.workplace.commons.Messages.get().container( 500 org.opencms.workplace.commons.Messages.ERR_COPY_TARGET_PARENT_FOLDER_MISSING_1, 501 target)); 502 } 503 } else { 504 // We cannot copy multiple resources to a single resource 505 throw new CmsVfsException( 506 org.opencms.workplace.commons.Messages.get().container( 507 org.opencms.workplace.commons.Messages.ERR_COPY_MULTI_TARGET_NOFOLDER_1, 508 target)); 509 } 510 } 511 512 Action action = m_actionCombo != null ? (Action)m_actionCombo.getValue() : Action.move; 513 514 overwrite = overwrite || isOverwriteExisting(); 515 if (!overwrite || action.equals(Action.move)) { 516 List<CmsResource> collidingResources = getExistingFileCollisions(targetFolder, targetName); 517 if (collidingResources != null) { 518 if (action.equals(Action.move)) { 519 throw new CmsVfsException( 520 org.opencms.workplace.commons.Messages.get().container( 521 org.opencms.workplace.commons.Messages.ERR_MOVE_FORCES_OVERWRITE_EXISTING_RESOURCE_0)); 522 } else { 523 showConfirmOverwrite(collidingResources); 524 return; 525 } 526 } 527 } 528 Map<CmsResource, CmsException> errors = new HashMap<CmsResource, CmsException>(); 529 530 //Check if dialog for macro resolver has to be shown: action correct?, makroMap==null (default, not set by dialog yet) 531 if ((action == Action.sub_sitemap) & (makroMap == null)) { 532 if (CmsSiteManager.isFolderWithMacros(getRootCms(), m_context.getResources().get(0).getRootPath())) { 533 showMacroResolverDialog(m_context.getResources().get(0)); 534 return; 535 } 536 } 537 if (targetName == null) { 538 for (CmsResource source : m_context.getResources()) { 539 try { 540 performSingleOperation(source, targetFolder, action, overwrite, makroMap); 541 } catch (CmsException e) { 542 errors.put(source, e); 543 LOG.error("Error while executing " + action + " on resource " + source.getRootPath(), e); 544 } 545 } 546 } else { 547 // this will only be the case in a single resource scenario 548 CmsResource source = m_context.getResources().get(0); 549 try { 550 performSingleOperation(source, targetFolder, targetName, action, overwrite, makroMap); 551 } catch (CmsException e) { 552 errors.put(source, e); 553 LOG.error( 554 "Error while executing " 555 + m_actionCombo.getValue().toString() 556 + " on resource " 557 + source.getRootPath(), 558 e); 559 } 560 } 561 562 if (!errors.isEmpty()) { 563 if (m_context instanceof CmsEmbeddedDialogContext) { 564 // In ADE, finish() would trigger a reload and cause the error message to not be displayed, 565 // and we can only trigger the dialog for a single resource there anyway 566 m_context.error(errors.values().iterator().next()); 567 } else { 568 m_context.finish(m_updateResources); 569 m_context.error(errors.values().iterator().next()); 570 } 571 } else { 572 m_context.finish(m_updateResources); 573 } 574 575 } catch (CmsException e) { 576 m_context.error(e); 577 } 578 } 579 580 /** 581 * Returns the cms context.<p> 582 * 583 * @return the cms context 584 */ 585 private CmsObject getCms() { 586 587 if (m_cms == null) { 588 m_cms = A_CmsUI.getCmsObject(); 589 } 590 return m_cms; 591 } 592 593 /** 594 * Returns the resources that collide with already existing resources.<p> 595 * 596 * @param targetFolder the target folder 597 * @param targetName name of the target if a single file's copy should be named differently 598 * 599 * @return the colliding resources or <code>null</code> if no collisions found 600 * 601 * @throws CmsException in case the checking the resources fails 602 */ 603 private List<CmsResource> getExistingFileCollisions(CmsResource targetFolder, String targetName) 604 throws CmsException { 605 606 List<CmsResource> collidingResources = new ArrayList<CmsResource>(); 607 608 String finalTarget = targetFolder.getRootPath(); 609 if (!finalTarget.endsWith("/")) { 610 finalTarget += "/"; 611 } 612 if (targetName == null) { 613 for (CmsResource source : m_context.getResources()) { 614 if (finalTarget.equals(CmsResource.getParentFolder(source.getRootPath()))) { 615 // copying to the same folder, a new name will be generated 616 return null; 617 } 618 String fileName = finalTarget + source.getName(); 619 if (getRootCms().existsResource(fileName, CmsResourceFilter.ALL)) { 620 collidingResources.add(source); 621 } 622 } 623 } else { 624 String fileName = finalTarget + targetName; 625 if (getRootCms().existsResource(fileName, CmsResourceFilter.ALL)) { 626 collidingResources.add(getRootCms().readResource(fileName, CmsResourceFilter.ALL)); 627 } 628 } 629 return collidingResources.isEmpty() ? null : collidingResources; 630 } 631 632 /** 633 * Returns the root cms context.<p> 634 * 635 * @return the root cms context 636 * 637 * @throws CmsException in case initializing the context fails 638 */ 639 private CmsObject getRootCms() throws CmsException { 640 641 if (m_rootCms == null) { 642 m_rootCms = OpenCms.initCmsObject(getCms()); 643 m_rootCms.getRequestContext().setSiteRoot("/"); 644 } 645 return m_rootCms; 646 } 647 648 /** 649 * Gets a name for the target resource.<p> 650 * 651 * @param source Source 652 * @param target Target 653 * @return Name 654 * @throws CmsException exception 655 */ 656 private String getTargetName(CmsResource source, CmsResource target) throws CmsException { 657 658 String name; 659 String folderRootPath = target.getRootPath(); 660 if (!folderRootPath.endsWith("/")) { 661 folderRootPath += "/"; 662 } 663 if (folderRootPath.equals(CmsResource.getParentFolder(source.getRootPath()))) { 664 name = OpenCms.getResourceManager().getNameGenerator().getCopyFileName( 665 getRootCms(), 666 folderRootPath, 667 source.getName()); 668 } else { 669 name = source.getName(); 670 } 671 return name; 672 } 673 674 /** 675 * Checks whether the folder has a default file of the type container page.<p> 676 * 677 * @param folder the folder to check 678 * 679 * @return <code>true</code> if the folder has a default file of the type container page 680 */ 681 private boolean hasContainerPageDefaultFile(CmsResource folder) { 682 683 try { 684 CmsResource defaultFile = A_CmsUI.getCmsObject().readDefaultFile( 685 folder, 686 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 687 return (defaultFile != null) && CmsResourceTypeXmlContainerPage.isContainerPage(defaultFile); 688 } catch (CmsSecurityException e) { 689 return false; 690 } 691 } 692 693 /** 694 * Initializes the form fields.<p> 695 * 696 * @return the form component 697 */ 698 private FormLayout initForm() { 699 700 FormLayout form = new FormLayout(); 701 form.setWidth("100%"); 702 m_targetPath = new CmsPathSelectField(); 703 m_targetPath.setCaption( 704 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_MOVE_TARGET_0)); 705 m_targetPath.setFileSelectCaption( 706 CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_SELECT_TARGET_CAPTION_0)); 707 m_targetPath.setResourceFilter(CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireFolder()); 708 m_targetPath.setWidth("100%"); 709 form.addComponent(m_targetPath); 710 711 if (m_dialogMode != DialogMode.move) { 712 m_actionCombo = new ComboBox(); 713 m_actionCombo.setCaption(CmsVaadinUtils.getMessageText(org.opencms.ui.Messages.GUI_COPYPAGE_COPY_MODE_0)); 714 m_actionCombo.setNullSelectionAllowed(false); 715 m_actionCombo.setNewItemsAllowed(false); 716 m_actionCombo.setWidth("100%"); 717 if (m_context.getResources().size() == 1) { 718 if (m_context.getResources().get(0).isFile()) { 719 m_actionCombo.addItem(Action.copy_all); 720 m_actionCombo.setItemCaption( 721 Action.copy_all, 722 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_AS_NEW_0)); 723 m_actionCombo.addItem(Action.copy_sibling_all); 724 m_actionCombo.setItemCaption( 725 Action.copy_sibling_all, 726 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_CREATE_SIBLING_0)); 727 if (m_dialogMode == DialogMode.copy_and_move) { 728 m_actionCombo.addItem(Action.move); 729 m_actionCombo.setItemCaption( 730 Action.move, 731 CmsVaadinUtils.getMessageText( 732 org.opencms.workplace.commons.Messages.GUI_COPY_MOVE_MOVE_FILE_0)); 733 } 734 } else { 735 CmsResource folder = m_context.getResources().get(0); 736 m_hasContainerPageDefaultFile = hasContainerPageDefaultFile(folder); 737 if (m_hasContainerPageDefaultFile) { 738 m_actionCombo.addItem(Action.container_page_automatic); 739 m_actionCombo.setItemCaption( 740 Action.container_page_automatic, 741 CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_AUTOMATIC_0)); 742 m_actionCombo.addItem(Action.container_page_copy); 743 m_actionCombo.setItemCaption( 744 Action.container_page_copy, 745 CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_CONTAINERPAGE_COPY_0)); 746 m_actionCombo.addItem(Action.container_page_reuse); 747 m_actionCombo.setItemCaption( 748 Action.container_page_reuse, 749 CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_CONTAINERPAGE_REUSE_0)); 750 } 751 if (CmsResourceTypeFolderSubSitemap.isSubSitemap(folder)) { 752 m_actionCombo.addItem(Action.sub_sitemap); 753 m_actionCombo.setItemCaption( 754 Action.sub_sitemap, 755 CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_SUBSITEMAP_0)); 756 } 757 m_actionCombo.addItem(Action.copy_sibling_mixed); 758 m_actionCombo.setItemCaption( 759 Action.copy_sibling_mixed, 760 CmsVaadinUtils.getMessageText( 761 org.opencms.workplace.commons.Messages.GUI_COPY_ALL_NO_SIBLINGS_0)); 762 m_actionCombo.addItem(Action.copy_all); 763 m_actionCombo.setItemCaption( 764 Action.copy_all, 765 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_ALL_0)); 766 m_actionCombo.addItem(Action.copy_sibling_all); 767 m_actionCombo.setItemCaption( 768 Action.copy_sibling_all, 769 CmsVaadinUtils.getMessageText( 770 org.opencms.workplace.commons.Messages.GUI_COPY_MULTI_CREATE_SIBLINGS_0)); 771 if (m_dialogMode == DialogMode.copy_and_move) { 772 m_actionCombo.addItem(Action.move); 773 m_actionCombo.setItemCaption( 774 Action.move, 775 CmsVaadinUtils.getMessageText( 776 org.opencms.workplace.commons.Messages.GUI_COPY_MOVE_MOVE_FOLDER_0)); 777 } 778 } 779 } else { 780 m_actionCombo.addItem(Action.copy_sibling_mixed); 781 m_actionCombo.setItemCaption( 782 Action.copy_sibling_mixed, 783 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_ALL_NO_SIBLINGS_0)); 784 m_actionCombo.addItem(Action.copy_all); 785 m_actionCombo.setItemCaption( 786 Action.copy_all, 787 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_ALL_0)); 788 m_actionCombo.addItem(Action.copy_sibling_all); 789 m_actionCombo.setItemCaption( 790 Action.copy_sibling_all, 791 CmsVaadinUtils.getMessageText( 792 org.opencms.workplace.commons.Messages.GUI_COPY_MULTI_CREATE_SIBLINGS_0)); 793 if (m_dialogMode == DialogMode.copy_and_move) { 794 m_actionCombo.addItem(Action.move); 795 m_actionCombo.setItemCaption( 796 Action.move, 797 CmsVaadinUtils.getMessageText( 798 org.opencms.workplace.commons.Messages.GUI_COPY_MOVE_MOVE_RESOURCES_0)); 799 } 800 } 801 m_actionCombo.setItemStyleGenerator(new ItemStyleGenerator() { 802 803 private static final long serialVersionUID = 1L; 804 805 public String getStyle(ComboBox source, Object itemId) { 806 807 String style = null; 808 if (m_defaultActions.contains(itemId)) { 809 style = "bold"; 810 } 811 return style; 812 } 813 }); 814 form.addComponent(m_actionCombo); 815 m_actionCombo.addValueChangeListener(event -> updateOverwriteExisting()); 816 } 817 818 if (m_context.getResources().size() > 1) { 819 m_overwriteExisting = new CheckBox( 820 CmsVaadinUtils.getMessageText(org.opencms.workplace.commons.Messages.GUI_COPY_MULTI_OVERWRITE_0)); 821 m_overwriteExisting.setValue(Boolean.FALSE); 822 form.addComponent(m_overwriteExisting); 823 824 updateOverwriteExisting(); 825 } 826 827 return form; 828 } 829 830 /** 831 * Checks the overwrite existing setting.<p> 832 * 833 * @return <code>true</code> if overwrite existing is set 834 */ 835 private boolean isOverwriteExisting() { 836 837 return (m_overwriteExisting != null) && m_overwriteExisting.getValue().booleanValue(); 838 } 839 840 /** 841 * Displays the confirm overwrite dialog.<p> 842 * 843 * @param collidingResources the colliding resources 844 */ 845 private void showConfirmOverwrite(List<CmsResource> collidingResources) { 846 847 final Window window = CmsBasicDialog.prepareWindow(); 848 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_CONFIRM_OVERWRITE_TITLE_0)); 849 final CmsConfirmationDialog dialog = new CmsConfirmationDialog( 850 CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_CONFIRM_OVERWRITE_MESSAGE_0), 851 new Runnable() { 852 853 public void run() { 854 855 window.close(); 856 submit(true, null); 857 } 858 }, 859 new Runnable() { 860 861 public void run() { 862 863 window.close(); 864 cancel(); 865 } 866 }); 867 dialog.displayResourceInfo(collidingResources); 868 window.setContent(dialog); 869 UI.getCurrent().addWindow(window); 870 } 871 872 /** 873 * Displays the resolve macro dialog.<p> 874 * 875 * @param resource to be copied. 876 */ 877 private void showMacroResolverDialog(CmsResource resource) { 878 879 final Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide); 880 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_COPY_MOVE_SET_MACRO_VALUES_TITLE_0)); 881 m_macroDialog = new CmsMacroResolverDialog(new Runnable() { 882 883 public void run() { 884 885 Map<String, String> map = getMacroMap(); 886 window.close(); 887 submit(true, map); //Overwrite true because this was checked first. If no overwrite, window is closed and this code isn't called 888 } 889 }, new Runnable() { 890 891 public void run() { 892 893 window.close(); 894 cancel(); 895 } 896 }, resource); 897 m_macroDialog.displayResourceInfo(Collections.singletonList(resource)); 898 window.setContent(m_macroDialog); 899 UI.getCurrent().addWindow(window); 900 } 901 902 /** 903 * Updates the default dialog actions.<p> 904 * 905 * @param targetRootPath the target root path 906 */ 907 private void updateDefaultActions(String targetRootPath) { 908 909 if (m_actionCombo != null) { 910 m_defaultActions.clear(); 911 String resPath = m_context.getResources().get(0).getRootPath(); 912 String parentFolder = CmsResource.getParentFolder(resPath); 913 if ((DialogMode.copy_and_move == m_dialogMode) && !parentFolder.equals(targetRootPath)) { 914 m_defaultActions.clear(); 915 m_defaultActions.add(Action.move); 916 } else if (m_context.getResources().size() == 1) { 917 if (m_context.getResources().get(0).isFile()) { 918 m_defaultActions.add(Action.copy_all); 919 } else { 920 m_defaultActions.add(Action.copy_sibling_mixed); 921 if (m_hasContainerPageDefaultFile) { 922 m_defaultActions.clear(); 923 m_defaultActions.add(Action.container_page_automatic); 924 m_defaultActions.add(Action.container_page_copy); 925 m_defaultActions.add(Action.container_page_reuse); 926 } 927 CmsResource folder = m_context.getResources().get(0); 928 if (CmsResourceTypeFolderSubSitemap.isSubSitemap(folder)) { 929 m_defaultActions.clear(); 930 m_defaultActions.add(Action.sub_sitemap); 931 } 932 } 933 } else { 934 m_defaultActions.add(Action.copy_sibling_mixed); 935 } 936 if (!m_defaultActions.isEmpty()) { 937 m_actionCombo.setValue(m_defaultActions.get(0)); 938 } 939 m_actionCombo.markAsDirty(); 940 } 941 } 942}