| 1 11 package org.eclipse.ui.actions; 12 13 import java.io.File ; 14 import java.lang.reflect.InvocationTargetException ; 15 import java.net.URI ; 16 import com.ibm.icu.text.MessageFormat; 17 import java.util.ArrayList ; 18 import java.util.Arrays ; 19 import java.util.List ; 20 21 import org.eclipse.core.commands.ExecutionException; 22 import org.eclipse.core.filesystem.EFS; 23 import org.eclipse.core.filesystem.IFileInfo; 24 import org.eclipse.core.filesystem.IFileStore; 25 import org.eclipse.core.resources.IContainer; 26 import org.eclipse.core.resources.IFile; 27 import org.eclipse.core.resources.IFolder; 28 import org.eclipse.core.resources.IProject; 29 import org.eclipse.core.resources.IResource; 30 import org.eclipse.core.resources.IWorkspace; 31 import org.eclipse.core.resources.IWorkspaceRoot; 32 import org.eclipse.core.resources.ResourcesPlugin; 33 import org.eclipse.core.resources.WorkspaceJob; 34 import org.eclipse.core.runtime.CoreException; 35 import org.eclipse.core.runtime.IAdaptable; 36 import org.eclipse.core.runtime.IPath; 37 import org.eclipse.core.runtime.IProgressMonitor; 38 import org.eclipse.core.runtime.IStatus; 39 import org.eclipse.core.runtime.MultiStatus; 40 import org.eclipse.core.runtime.OperationCanceledException; 41 import org.eclipse.core.runtime.Path; 42 import org.eclipse.core.runtime.Status; 43 import org.eclipse.core.runtime.SubProgressMonitor; 44 import org.eclipse.jface.dialogs.ErrorDialog; 45 import org.eclipse.jface.dialogs.IDialogConstants; 46 import org.eclipse.jface.dialogs.IInputValidator; 47 import org.eclipse.jface.dialogs.InputDialog; 48 import org.eclipse.jface.dialogs.MessageDialog; 49 import org.eclipse.jface.operation.IRunnableWithProgress; 50 import org.eclipse.jface.window.Window; 51 import org.eclipse.osgi.util.NLS; 52 import org.eclipse.swt.SWT; 53 import org.eclipse.swt.widgets.Display; 54 import org.eclipse.swt.widgets.Shell; 55 import org.eclipse.ui.PlatformUI; 56 import org.eclipse.ui.dialogs.IOverwriteQuery; 57 import org.eclipse.ui.ide.undo.AbstractWorkspaceOperation; 58 import org.eclipse.ui.ide.undo.CopyResourcesOperation; 59 import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; 60 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; 61 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; 62 import org.eclipse.ui.internal.ide.StatusUtil; 63 import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils; 64 import org.eclipse.ui.wizards.datatransfer.FileStoreStructureProvider; 65 import org.eclipse.ui.wizards.datatransfer.ImportOperation; 66 67 74 public class CopyFilesAndFoldersOperation { 75 76 80 private MultiStatus errorStatus; 81 82 85 private Shell messageShell; 86 87 90 private boolean canceled = false; 91 92 95 private boolean alwaysOverwrite = false; 96 97 private String [] modelProviderIds; 98 99 109 static IPath getAutoNewNameFor(IPath originalName, IWorkspace workspace) { 110 int counter = 1; 111 String resourceName = originalName.lastSegment(); 112 IPath leadupSegment = originalName.removeLastSegments(1); 113 114 while (true) { 115 String nameSegment; 116 117 if (counter > 1) { 118 nameSegment = NLS 119 .bind( 120 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyNameTwoArgs, 121 new Integer (counter), resourceName); 122 } else { 123 nameSegment = NLS 124 .bind( 125 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyNameOneArg, 126 resourceName); 127 } 128 129 IPath pathToTry = leadupSegment.append(nameSegment); 130 131 if (!workspace.getRoot().exists(pathToTry)) { 132 return pathToTry; 133 } 134 135 counter++; 136 } 137 } 138 139 145 public CopyFilesAndFoldersOperation(Shell shell) { 146 messageShell = shell; 147 } 148 149 156 protected boolean canPerformAutoRename() { 157 return true; 158 } 159 160 167 protected String getDeepCheckQuestion(IResource source) { 168 return NLS 169 .bind( 170 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_deepCopyQuestion, 171 source.getFullPath().makeRelative()); 172 } 173 174 181 IStatus checkExist(IFileStore[] stores) { 182 MultiStatus multiStatus = new MultiStatus(PlatformUI.PLUGIN_ID, 183 IStatus.OK, getProblemsMessage(), null); 184 185 for (int i = 0; i < stores.length; i++) { 186 if (stores[i].fetchInfo().exists() == false) { 187 String message = NLS 188 .bind( 189 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted, 190 stores[i].getName()); 191 IStatus status = new Status(IStatus.ERROR, 192 PlatformUI.PLUGIN_ID, IStatus.OK, message, null); 193 multiStatus.add(status); 194 } 195 } 196 return multiStatus; 197 } 198 199 206 IStatus checkExist(IResource[] resources) { 207 MultiStatus multiStatus = new MultiStatus(PlatformUI.PLUGIN_ID, 208 IStatus.OK, getProblemsMessage(), null); 209 210 for (int i = 0; i < resources.length; i++) { 211 IResource resource = resources[i]; 212 if (resource != null) { 213 URI location = resource.getLocationURI(); 214 String message = null; 215 if (location != null) { 216 IFileInfo info = IDEResourceInfoUtils.getFileInfo(location); 217 if (info == null || info.exists() == false) { 218 if (resource.isLinked()) { 219 message = NLS 220 .bind( 221 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_missingLinkTarget, 222 resource.getName()); 223 } else { 224 message = NLS 225 .bind( 226 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted, 227 resource.getName()); 228 } 229 } 230 } 231 if (message != null) { 232 IStatus status = new Status(IStatus.ERROR, 233 PlatformUI.PLUGIN_ID, IStatus.OK, message, null); 234 multiStatus.add(status); 235 } 236 } 237 } 238 return multiStatus; 239 } 240 241 254 private int checkOverwrite(final IResource source, 255 final IResource destination) { 256 final int[] result = new int[1]; 257 258 Runnable query = new Runnable () { 260 public void run() { 261 String message; 262 int resultId[] = { IDialogConstants.YES_ID, 263 IDialogConstants.YES_TO_ALL_ID, IDialogConstants.NO_ID, 264 IDialogConstants.CANCEL_ID }; 265 String labels[] = new String [] { IDialogConstants.YES_LABEL, 266 IDialogConstants.YES_TO_ALL_LABEL, 267 IDialogConstants.NO_LABEL, 268 IDialogConstants.CANCEL_LABEL }; 269 270 if (destination.getType() == IResource.FOLDER) { 271 if (homogenousResources(source, destination)) { 272 message = NLS 273 .bind( 274 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteMergeQuestion, 275 destination.getFullPath() 276 .makeRelative()); 277 } else { 278 if (destination.isLinked()) { 279 message = NLS 280 .bind( 281 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteNoMergeLinkQuestion, 282 destination.getFullPath() 283 .makeRelative()); 284 } else { 285 message = NLS 286 .bind( 287 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteNoMergeNoLinkQuestion, 288 destination.getFullPath() 289 .makeRelative()); 290 } 291 resultId = new int[] { IDialogConstants.YES_ID, 292 IDialogConstants.NO_ID, 293 IDialogConstants.CANCEL_ID }; 294 labels = new String [] { IDialogConstants.YES_LABEL, 295 IDialogConstants.NO_LABEL, 296 IDialogConstants.CANCEL_LABEL }; 297 } 298 } else { 299 String [] bindings = new String [] { 300 IDEResourceInfoUtils.getLocationText(destination), 301 IDEResourceInfoUtils 302 .getDateStringValue(destination), 303 IDEResourceInfoUtils.getLocationText(source), 304 IDEResourceInfoUtils.getDateStringValue(source) }; 305 message = NLS 306 .bind( 307 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteWithDetailsQuestion, 308 bindings); 309 } 310 MessageDialog dialog = new MessageDialog( 311 messageShell, 312 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceExists, 313 null, message, MessageDialog.QUESTION, labels, 0); 314 dialog.open(); 315 if (dialog.getReturnCode() == SWT.DEFAULT) { 316 result[0] = IDialogConstants.CANCEL_ID; 319 } else { 320 result[0] = resultId[dialog.getReturnCode()]; 321 } 322 } 323 }; 324 messageShell.getDisplay().syncExec(query); 325 return result[0]; 326 } 327 328 338 private void collectExistingReadonlyFiles(IPath destinationPath, 339 IResource[] copyResources, ArrayList existing) { 340 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); 341 342 for (int i = 0; i < copyResources.length; i++) { 343 IResource source = copyResources[i]; 344 IPath newDestinationPath = destinationPath.append(source.getName()); 345 IResource newDestination = workspaceRoot 346 .findMember(newDestinationPath); 347 IFolder folder; 348 349 if (newDestination == null) { 350 continue; 351 } 352 folder = getFolder(newDestination); 353 if (folder != null) { 354 IFolder sourceFolder = getFolder(source); 355 356 if (sourceFolder != null) { 357 try { 358 collectExistingReadonlyFiles(newDestinationPath, 359 sourceFolder.members(), existing); 360 } catch (CoreException exception) { 361 recordError(exception); 362 } 363 } 364 } else { 365 IFile file = getFile(newDestination); 366 367 if (file != null) { 368 if (file.isReadOnly()) { 369 existing.add(file); 370 } 371 if (getValidateConflictSource()) { 372 IFile sourceFile = getFile(source); 373 if (sourceFile != null) { 374 existing.add(sourceFile); 375 } 376 } 377 } 378 } 379 } 380 } 381 382 397 protected void copy(IResource[] resources, IPath destination, 398 IProgressMonitor subMonitor) throws CoreException { 399 400 subMonitor 401 .beginTask( 402 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_CopyResourcesTask, 403 resources.length); 404 405 for (int i = 0; i < resources.length; i++) { 406 IResource source = resources[i]; 407 IPath destinationPath = destination.append(source.getName()); 408 IWorkspace workspace = source.getWorkspace(); 409 IWorkspaceRoot workspaceRoot = workspace.getRoot(); 410 IResource existing = workspaceRoot.findMember(destinationPath); 411 if (source.getType() == IResource.FOLDER && existing != null) { 412 if (homogenousResources(source, existing)) { 416 IResource[] children = ((IContainer) source).members(); 417 copy(children, destinationPath, new SubProgressMonitor( 418 subMonitor, 1)); 419 } else { 420 delete(existing, new SubProgressMonitor(subMonitor, 0)); 423 source.copy(destinationPath, IResource.SHALLOW, 424 new SubProgressMonitor(subMonitor, 1)); 425 } 426 } else { 427 if (existing != null) { 428 if (homogenousResources(source, existing)) { 429 copyExisting(source, existing, new SubProgressMonitor( 430 subMonitor, 1)); 431 } else { 432 delete(existing, new SubProgressMonitor(subMonitor, 0)); 436 source.copy(destinationPath, IResource.SHALLOW, 437 new SubProgressMonitor(subMonitor, 1)); 438 } 439 } else { 440 source.copy(destinationPath, IResource.SHALLOW, 441 new SubProgressMonitor(subMonitor, 1)); 442 443 } 444 445 if (subMonitor.isCanceled()) { 446 throw new OperationCanceledException(); 447 } 448 } 449 } 450 } 451 452 464 private void copyExisting(IResource source, IResource existing, 465 IProgressMonitor subMonitor) throws CoreException { 466 IFile existingFile = getFile(existing); 467 468 if (existingFile != null) { 469 IFile sourceFile = getFile(source); 470 471 if (sourceFile != null) { 472 existingFile.setContents(sourceFile.getContents(), 473 IResource.KEEP_HISTORY, new SubProgressMonitor( 474 subMonitor, 0)); 475 } 476 } 477 } 478 479 493 public IResource[] copyResources(final IResource[] resources, 494 IContainer destination) { 495 return copyResources(resources, destination, true, null); 496 } 497 498 515 public IResource[] copyResourcesInCurrentThread( 516 final IResource[] resources, IContainer destination, 517 IProgressMonitor monitor) { 518 return copyResources(resources, destination, false, monitor); 519 } 520 521 530 private IResource[] copyResources(final IResource[] resources, 531 IContainer destination, boolean fork, IProgressMonitor monitor) { 532 final IPath destinationPath = destination.getFullPath(); 533 final IResource[][] copiedResources = new IResource[1][0]; 534 535 IStatus resourceStatus = checkExist(resources); 539 if (resourceStatus.getSeverity() != IStatus.OK) { 540 displayError(resourceStatus); 541 return copiedResources[0]; 542 } 543 String errorMsg = validateDestination(destination, resources); 544 if (errorMsg != null) { 545 displayError(errorMsg); 546 return copiedResources[0]; 547 } 548 549 IRunnableWithProgress op = new IRunnableWithProgress() { 550 public void run(IProgressMonitor monitor) { 551 copyResources(resources, destinationPath, copiedResources, 552 monitor); 553 } 554 }; 555 556 try { 557 PlatformUI.getWorkbench().getProgressService().run(fork, true, op); 558 } catch (InterruptedException e) { 559 return copiedResources[0]; 560 } catch (InvocationTargetException e) { 561 display(e); 562 } 563 564 if (errorStatus != null) { 566 displayError(errorStatus); 567 errorStatus = null; 568 } 569 570 return copiedResources[0]; 571 } 572 573 579 protected boolean isMove() { 580 return false; 581 } 582 583 private void display(InvocationTargetException e) { 584 IDEWorkbenchPlugin.getDefault().getLog().log( 587 StatusUtil.newStatus(IStatus.ERROR, MessageFormat.format( 588 "Exception in {0}.performCopy(): {1}", new Object [] { getClass().getName(), 590 e.getTargetException() }), null)); 591 displayError(NLS 592 .bind( 593 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError, 594 e.getTargetException().getMessage())); 595 } 596 597 612 public void copyFiles(URI [] uris, IContainer destination) { 613 IFileStore[] stores = buildFileStores(uris); 614 if (stores == null) { 615 return; 616 } 617 618 copyFileStores(destination, stores, true, null); 619 } 620 621 637 public void copyFilesInCurrentThread(URI [] uris, IContainer destination, 638 IProgressMonitor monitor) { 639 IFileStore[] stores = buildFileStores(uris); 640 if (stores == null) { 641 return; 642 } 643 644 copyFileStores(destination, stores, false, monitor); 645 } 646 647 654 private IFileStore[] buildFileStores(URI [] uris) { 655 IFileStore[] stores = new IFileStore[uris.length]; 656 for (int i = 0; i < uris.length; i++) { 657 IFileStore store; 658 try { 659 store = EFS.getStore(uris[i]); 660 } catch (CoreException e) { 661 IDEWorkbenchPlugin.log(e.getMessage(), e); 662 reportFileInfoNotFound(uris[i].toString()); 663 return null; 664 } 665 if (store == null) { 666 reportFileInfoNotFound(uris[i].toString()); 667 return null; 668 } 669 stores[i] = store; 670 } 671 return stores; 672 673 } 674 675 690 public void copyFiles(final String [] fileNames, IContainer destination) { 691 IFileStore[] stores = buildFileStores(fileNames); 692 if (stores == null) { 693 return; 694 } 695 696 copyFileStores(destination, stores, true, null); 697 } 698 699 715 public void copyFilesInCurrentThread(final String [] fileNames, 716 IContainer destination, IProgressMonitor monitor) { 717 IFileStore[] stores = buildFileStores(fileNames); 718 if (stores == null) { 719 return; 720 } 721 722 copyFileStores(destination, stores, false, monitor); 723 } 724 725 732 private IFileStore[] buildFileStores(final String [] fileNames) { 733 IFileStore[] stores = new IFileStore[fileNames.length]; 734 for (int i = 0; i < fileNames.length; i++) { 735 IFileStore store = IDEResourceInfoUtils.getFileStore(fileNames[i]); 736 if (store == null) { 737 reportFileInfoNotFound(fileNames[i]); 738 return null; 739 } 740 stores[i] = store; 741 } 742 return stores; 743 } 744 745 750 private void reportFileInfoNotFound(final String fileName) { 751 752 messageShell.getDisplay().syncExec(new Runnable () { 753 public void run() { 754 ErrorDialog 755 .openError( 756 messageShell, 757 getProblemsTitle(), 758 NLS 759 .bind( 760 IDEWorkbenchMessages.CopyFilesAndFoldersOperation_infoNotFound, 761 fileName), null); 762 } 763 }); 764 } 765
|