/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Serge Beauchamp (Freescale Semiconductor) - Bug 229633
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 472784
 *     Patrik Suzzi <psuzzi@gmail.com> - Bug 489250
 *******************************************************************************/
package org.eclipse.ui.actions;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.ide.dialogs.ImportTypeDialog;
import org.eclipse.ui.ide.undo.AbstractWorkspaceOperation;
import org.eclipse.ui.ide.undo.CopyResourcesOperation;
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.StatusUtil;
import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.wizards.datatransfer.FileStoreStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;

import com.ibm.icu.text.MessageFormat;


/**
 * Perform the copy of file and folder resources from the clipboard when paste
 * action is invoked.
 * <p>
 * This class may be instantiated; it is not intended to be subclassed.
 * </p>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class CopyFilesAndFoldersOperation {

	/**
	 * Status containing the errors detected when running the operation or
	 * <code>null</code> if no errors detected.
	 */
	private MultiStatus errorStatus;

	/**
	 * The parent shell used to show any dialogs.
	 */
	private Shell messageShell;

	/**
	 * Whether or not the copy has been canceled by the user.
	 */
	private boolean canceled = false;

	/**
	 * Whether or not the operation creates virtual folders and links instead of folders
	 * and files.
	 */
	private boolean createVirtualFoldersAndLinks = false;

	/**
	 * Whether or not the operation creates links instead of folders and files.
	 */
	private boolean createLinks = false;

	private String relativeVariable = null;
	/**
	 * Overwrite all flag.
	 */
	private boolean alwaysOverwrite = false;

	private String[] modelProviderIds;

	/**
	 * Returns a new name for a copy of the resource at the given path in the
	 * given workspace. This name is determined automatically.
	 *
	 * @param originalName
	 *            the full path of the resource
	 * @param workspace
	 *            the workspace
	 * @return the new full path for the copy
	 */
	static IPath getAutoNewNameFor(IPath originalName, IWorkspace workspace) {
		String resourceName = originalName.lastSegment();
		IPath leadupSegment = originalName.removeLastSegments(1);
		boolean isFile = !originalName.hasTrailingSeparator();

		String newName = computeNewName(resourceName, isFile);
		while (true) {
			IPath pathToTry = leadupSegment.append(newName);
			if (!workspace.getRoot().exists(pathToTry)) {
				return pathToTry;
			}
			newName = computeNewName(newName, isFile);
		}
	}

	private static String computeNewName(String str, boolean isFile) {
		int lastIndexOfDot = str.lastIndexOf('.');
		String fileExtension = ""; //$NON-NLS-1$
		String fileNameNoExtension = str;
		if (isFile && lastIndexOfDot > 0) {
			fileExtension = str.substring(lastIndexOfDot);
			fileNameNoExtension = str.substring(0, lastIndexOfDot);
		}
		Pattern p = Pattern.compile("[0-9]+$"); //$NON-NLS-1$
		Matcher m = p.matcher(fileNameNoExtension);
		if (m.find()) {
			// String ends with a number: increment it by 1
			int newNumber = Integer.parseInt(m.group()) + 1;
			String numberStr = m.replaceFirst(Integer.toString(newNumber));
			return numberStr + fileExtension;
		}
		return fileNameNoExtension + "2" + fileExtension; //$NON-NLS-1$
	}

	/**
	 * Creates a new operation initialized with a shell.
	 *
	 * @param shell
	 *            parent shell for error dialogs
	 */
	public CopyFilesAndFoldersOperation(Shell shell) {
		messageShell = shell;
	}

	/**
	 * Returns whether this operation is able to perform on-the-fly
	 * auto-renaming of resources with name collisions.
	 *
	 * @return <code>true</code> if auto-rename is supported, and
	 *         <code>false</code> otherwise
	 */
	protected boolean canPerformAutoRename() {
		return true;
	}

	/**
	 * Returns the message for querying deep copy/move of a linked resource.
	 *
	 * @param source
	 *            resource the query is made for
	 * @return the deep query message
	 */
	protected String getDeepCheckQuestion(IResource source) {
		return NLS
				.bind(
						IDEWorkbenchMessages.CopyFilesAndFoldersOperation_deepCopyQuestion,
						source.getFullPath().makeRelative());
	}

	/**
	 * Checks whether the infos exist.
	 *
	 * @param stores
	 *            the file infos to test
	 * @return Multi status with one error message for each missing file.
	 */
	IStatus checkExist(IFileStore[] stores) {
		MultiStatus multiStatus = new MultiStatus(PlatformUI.PLUGIN_ID,
				IStatus.OK, getProblemsMessage(), null);

		for (IFileStore store : stores) {
			if (store.fetchInfo().exists() == false) {
				String message = NLS.bind(IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted,
								store.getName());
				IStatus status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, null);
				multiStatus.add(status);
			}
		}
		return multiStatus;
	}

	/**
	 * Checks whether the resources with the given names exist.
	 *
	 * @param resources
	 *            IResources to checl
	 * @return Multi status with one error message for each missing file.
	 */
	IStatus checkExist(IResource[] resources) {
		MultiStatus multiStatus = new MultiStatus(PlatformUI.PLUGIN_ID,
				IStatus.OK, getProblemsMessage(), null);

		for (IResource resource : resources) {
			if (resource != null && !resource.isVirtual()) {
				URI location = resource.getLocationURI();
				String message = null;
				if (location != null) {
					IFileInfo info = IDEResourceInfoUtils.getFileInfo(location);
					if (info == null || info.exists() == false) {
						if (resource.isLinked()) {
							message = NLS
									.bind(
											IDEWorkbenchMessages.CopyFilesAndFoldersOperation_missingLinkTarget,
											resource.getName());
						} else {
							message = NLS
									.bind(
											IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted,
											resource.getName());
						}
					}
				}
				if (message != null) {
					IStatus status = new Status(IStatus.ERROR,
							PlatformUI.PLUGIN_ID, IStatus.OK, message, null);
					multiStatus.add(status);
				}
			}
		}
		return multiStatus;
	}

	/**
	 * Check if the user wishes to overwrite the supplied resource or all
	 * resources.
	 *
	 * @param source
	 *            the source resource
	 * @param destination
	 *            the resource to be overwritten
	 * @return one of IDialogConstants.YES_ID, IDialogConstants.YES_TO_ALL_ID,
	 *         IDialogConstants.NO_ID, IDialogConstants.CANCEL_ID indicating
	 *         whether the current resource or all resources can be overwritten,
	 *         or if the operation should be canceled.
	 */
	private int checkOverwrite(final IResource source,
			final IResource destination) {
		final int[] result = new int[1];

		// Dialogs need to be created and opened in the UI thread
		Runnable query = new Runnable() {
			@Override
			public void run() {
				String message;
				int resultId[] = { IDialogConstants.YES_ID,
						IDialogConstants.YES_TO_ALL_ID, IDialogConstants.NO_ID,
						IDialogConstants.CANCEL_ID };
				String labels[] = new String[] { IDialogConstants.YES_LABEL,
						IDialogConstants.YES_TO_ALL_LABEL,
						IDialogConstants.NO_LABEL,
						IDialogConstants.CANCEL_LABEL };

				if (destination.getType() == IResource.FOLDER) {
					if (homogenousResources(source, destination)) {
						message = NLS
								.bind(
										IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteMergeQuestion,
										destination.getFullPath()
												.makeRelative());
					} else {
						if (destination.isLinked()) {
							message = NLS
									.bind(
											IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteNoMergeLinkQuestion,
											destination.getFullPath()
													.makeRelative());
						} else {
							message = NLS
									.bind(
											IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteNoMergeNoLinkQuestion,
											destination.getFullPath()
													.makeRelative());
						}
						resultId = new int[] { IDialogConstants.YES_ID,
								IDialogConstants.NO_ID,
								IDialogConstants.CANCEL_ID };
						labels = new String[] { IDialogConstants.YES_LABEL,
								IDialogConstants.NO_LABEL,
								IDialogConstants.CANCEL_LABEL };
					}
				} else {
					String[] bindings = new String[] {
							IDEResourceInfoUtils.getLocationText(destination),
							IDEResourceInfoUtils
									.getDateStringValue(destination),
							IDEResourceInfoUtils.getLocationText(source),
							IDEResourceInfoUtils.getDateStringValue(source) };
					message = NLS
							.bind(
									IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteWithDetailsQuestion,
									bindings);
				}
				MessageDialog dialog = new MessageDialog(
						messageShell,
						IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceExists,
						null, message, MessageDialog.QUESTION, 0, labels) {
					@Override
					protected int getShellStyle() {
						return super.getShellStyle() | SWT.SHEET;
					}
				};
				dialog.open();
				if (dialog.getReturnCode() == SWT.DEFAULT) {
					// A window close returns SWT.DEFAULT, which has to be
					// mapped to a cancel
					result[0] = IDialogConstants.CANCEL_ID;
				} else {
					result[0] = resultId[dialog.getReturnCode()];
				}
			}
		};
		messageShell.getDisplay().syncExec(query);
		return result[0];
	}

	/**
	 * Recursively collects existing files in the specified destination path.
	 *
	 * @param destinationPath
	 *            destination path to check for existing files
	 * @param copyResources
	 *            resources that may exist in the destination
	 * @param existing
	 *            holds the collected existing files
	 */
	private void collectExistingReadonlyFiles(IPath destinationPath,
			IResource[] copyResources, ArrayList existing) {
		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

		for (IResource resource : copyResources) {
			IPath newDestinationPath = destinationPath.append(resource.getName());
			IResource newDestination = workspaceRoot.findMember(newDestinationPath);
			IFolder folder;

			if (newDestination == null) {
				continue;
			}
			folder = getFolder(newDestination);
			if (folder != null) {
				IFolder sourceFolder = getFolder(resource);

				if (sourceFolder != null) {
					try {
						collectExistingReadonlyFiles(newDestinationPath,
								sourceFolder.members(), existing);
					} catch (CoreException exception) {
						recordError(exception);
					}
				}
			} else {
				IFile file = getFile(newDestination);

				if (file != null) {
					if (file.isReadOnly()) {
						existing.add(file);
					}
					if (getValidateConflictSource()) {
						IFile sourceFile = getFile(resource);
						if (sourceFile != null) {
							existing.add(sourceFile);
						}
					}
				}
			}
		}
	}

	/**
	 * Copies the resources to the given destination. This method is called
	 * recursively to merge folders during folder copy.
	 *
	 * @param resources
	 *            the resources to copy
	 * @param destination
	 *            destination to which resources will be copied
	 * @param monitor
	 *            a progress monitor for showing progress and for cancelation
	 *
	 * @deprecated As of 3.3, the work is performed in the undoable operation
	 *             created in
	 *             {@link #getUndoableCopyOrMoveOperation(IResource[], IPath)}
	 */
	@Deprecated
	protected void copy(IResource[] resources, IPath destination, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor,
				IDEWorkbenchMessages.CopyFilesAndFoldersOperation_CopyResourcesTask, resources.length);

		for (IResource resource : resources) {
			SubMonitor iterationMonitor = subMonitor.split(1).setWorkRemaining(100);
			IPath destinationPath = destination.append(resource.getName());
			IWorkspace workspace = resource.getWorkspace();
			IWorkspaceRoot workspaceRoot = workspace.getRoot();
			IResource existing = workspaceRoot.findMember(destinationPath);
			if (resource.getType() == IResource.FOLDER && existing != null) {
				// the resource is a folder and it exists in the destination,
				// copy the
				// children of the folder.
				if (homogenousResources(resource, existing)) {
					IResource[] children = ((IContainer) resource).members();
					copy(children, destinationPath, iterationMonitor.split(100));
				} else {
					// delete the destination folder, copying a linked folder
					// over an unlinked one or vice versa. Fixes bug 28772.
					delete(existing, iterationMonitor.split(10));
					resource.copy(destinationPath, IResource.SHALLOW, iterationMonitor.split(90));
				}
			} else {
				if (existing != null) {
					if (homogenousResources(resource, existing)) {
						copyExisting(resource, existing, iterationMonitor.split(100));
					} else {
						if (existing != null) {
							// Copying a linked resource over unlinked or vice
							// versa.
							// Can't use setContents here. Fixes bug 28772.
							delete(existing, iterationMonitor.split(10));
						}
						iterationMonitor.setWorkRemaining(100);

						if ((createLinks || createVirtualFoldersAndLinks) && (resource.isLinked() == false)
								&& (resource.isVirtual() == false)) {
							if (resource.getType() == IResource.FILE) {
								IFile file = workspaceRoot.getFile(destinationPath);
								file.createLink(createRelativePath(resource.getLocationURI(), file), 0,
										iterationMonitor.split(100));
							} else {
								IFolder folder = workspaceRoot.getFolder(destinationPath);
								if (createVirtualFoldersAndLinks) {
									folder.create(IResource.VIRTUAL, true, iterationMonitor.split(1));
									IResource[] members = ((IContainer) resource).members();
									if (members.length > 0)
										copy(members, destinationPath, iterationMonitor.split(99));
								} else
									folder.createLink(createRelativePath(resource.getLocationURI(), folder), 0,
											iterationMonitor.split(100));
							}
						} else
							resource.copy(destinationPath, IResource.SHALLOW, iterationMonitor.split(100));
					}
				}
			}
		}
	}

	/**
	 * Transform an absolute path URI to a relative path one (i.e. from
	 * "C:\foo\bar\file.txt" to "VAR\file.txt" granted that the relativeVariable
	 * is "VAR" and points to "C:\foo\bar\").
	 *
	 * @param locationURI
	 * @return an URI that was made relative to a variable
	 */
	private URI createRelativePath(URI locationURI, IResource resource) {
		if (relativeVariable == null)
			return locationURI;
		IPath location = URIUtil.toPath(locationURI);
		IPath result;
		try {
			result = URIUtil.toPath(resource.getPathVariableManager().convertToRelative(URIUtil.toURI(location), true, relativeVariable));
		} catch (CoreException e) {
			return locationURI;
		}
		return URIUtil.toURI(result);
	}

	/**
	 * Sets the content of the existing file to the source file content.
	 *
	 * @param source
	 *            source file to copy
	 * @param existing
	 *            existing file to set the source content in
	 * @param subMonitor
	 *            a progress monitor for showing progress and for cancelation
	 * @throws CoreException
	 *             setContents failed
	 */
	private void copyExisting(IResource source, IResource existing, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, 1);
		IFile existingFile = getFile(existing);

		if (existingFile != null) {
			IFile sourceFile = getFile(source);

			if (sourceFile != null) {
				existingFile.setContents(sourceFile.getContents(), IResource.KEEP_HISTORY, subMonitor.split(1));
			}
		}
	}

	/**
	 * Copies the given resources to the destination. The current Thread is
	 * halted while the resources are copied using a WorkspaceModifyOperation.
	 * This method should be called from the UIThread.
	 *
	 * @param resources
	 *            the resources to copy
	 * @param destination
	 *            destination to which resources will be copied
	 * @return the resources which actually got copied
	 * @see WorkspaceModifyOperation
	 * @see Display#getThread()
	 * @see Thread#currentThread()
	 */
	public IResource[] copyResources(final IResource[] resources,
			IContainer destination) {
		return copyResources(resources, destination, true);
	}

	/**
	 * Copies the given resources to the destination in the current Thread
	 * without forking a new Thread or blocking using a
	 * WorkspaceModifyOperation. It recommended that this method only be called
	 * from a {@link WorkspaceJob} to avoid possible deadlock.
	 *
	 * @param resources
	 *            the resources to copy
	 * @param destination
	 *            destination to which resources will be copied
	 * @param monitor
	 *            the monitor that information will be sent to.
	 * @return IResource[] the resulting {@link IResource}[]
	 * @see WorkspaceModifyOperation
	 * @see WorkspaceJob
	 * @since 3.2
	 */
	public IResource[] copyResourcesInCurrentThread(
			final IResource[] resources, IContainer destination,
			IProgressMonitor monitor) {
		return copyResources(resources, destination, false);
	}

	/**
	 * Copies the given resources to the destination.
	 *
	 * @param resources
	 *            the resources to copy
	 * @param destination
	 *            destination to which resources will be copied
	 * @return IResource[] the resulting {@link IResource}[]
	 */
	private IResource[] copyResources(final IResource[] resources,
			IContainer destination, boolean fork) {
		final IPath destinationPath = destination.getFullPath();
		final IResource[][] copiedResources = new IResource[1][0];

		// test resources for existence separate from validate API.
		// Validate is performance critical and resource exists
		// check is potentially slow. Fixes bugs 16129/28602.
		IStatus resourceStatus = checkExist(resources);
		if (resourceStatus.getSeverity() != IStatus.OK) {
			displayError(resourceStatus);
			return copiedResources[0];
		}
		String errorMsg = validateDestination(destination, resources);
		if (errorMsg != null) {
			displayError(errorMsg);
			return copiedResources[0];
		}

		IRunnableWithProgress op = new IRunnableWithProgress() {
			@Override
			public void run(IProgressMonitor monitor) {
				copyResources(resources, destinationPath, copiedResources,
						monitor);
			}
		};

		try {
			PlatformUI.getWorkbench().getProgressService().run(fork, true, op);
		} catch (InterruptedException e) {
			return copiedResources[0];
		} catch (InvocationTargetException e) {
			display(e);
		}

		// If errors occurred, open an Error dialog
		if (errorStatus != null) {
			displayError(errorStatus);
			errorStatus = null;
		}

		return copiedResources[0];
	}

	/**
	 * Return whether the operation is a move or a copy
	 *
	 * @return whether the operation is a move or a copy
	 * @since 3.2
	 */
	protected boolean isMove() {
		return false;
	}

	private void display(InvocationTargetException e) {
		// CoreExceptions are collected above, but unexpected runtime
		// exceptions and errors may still occur.
		IDEWorkbenchPlugin.getDefault().getLog().log(
				StatusUtil.newStatus(IStatus.ERROR, MessageFormat.format(
						"Exception in {0}.performCopy(): {1}", //$NON-NLS-1$
						getClass().getName(), e.getTargetException()), null));
		displayError(NLS
				.bind(
						IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError,
						e.getTargetException().getMessage()));
	}

	/**
	 * Copies the given URIS and folders to the destination. The current Thread
	 * is halted while the resources are copied using a
	 * WorkspaceModifyOperation. This method should be called from the UI
	 * Thread.
	 *
	 * @param uris
	 *            the URIs to copy
	 * @param destination
	 *            destination to which files will be copied
	 * @see WorkspaceModifyOperation
	 * @see Display#getThread()
	 * @see Thread#currentThread()
	 * @since 3.2
	 */
	public void copyFiles(URI[] uris, IContainer destination) {
		IFileStore[] stores = buildFileStores(uris);
		if (stores == null) {
			return;
		}

		copyFileStores(destination, stores, true, null);
	}

	/**
	 * Copies the given files and folders to the destination without forking a
	 * new Thread or blocking using a WorkspaceModifyOperation. It is
	 * recommended that this method only be called from a {@link WorkspaceJob}
	 * to avoid possible deadlock.
	 *
	 * @param uris
	 *            the URIs to copy
	 * @param destination
	 *            destination to which URIS will be copied
	 * @param monitor
	 *            the monitor that information will be sent to.
	 * @see WorkspaceModifyOperation
	 * @see WorkspaceJob
	 * @since 3.2
	 */
	public void copyFilesInCurrentThread(URI[] uris, IContainer destination,
			IProgressMonitor monitor) {
		IFileStore[] stores = buildFileStores(uris);
		if (stores == null) {
			return;
		}

		copyFileStores(destination, stores, false, monitor);
	}

	/**
	 * Build the collection of fileStores that map to fileNames. If any of them
	 * cannot be found then match then return <code>null</code>.
	 *
	 * @param uris
	 * @return IFileStore[]
	 */
	private IFileStore[] buildFileStores(URI[] uris) {
		IFileStore[] stores = new IFileStore[uris.length];
		for (int i = 0; i < uris.length; i++) {
			IFileStore store;
			try {
				store = EFS.getStore(uris[i]);
			} catch (CoreException e) {
				StatusManager.getManager().handle(e, IDEWorkbenchPlugin.IDE_WORKBENCH);
				reportFileInfoNotFound(uris[i].toString());
				return null;
			}
			if (store == null) {
				reportFileInfoNotFound(uris[i].toString());
				return null;
			}
			stores[i] = store;
		}
		return stores;

	}

	/**
	 * Depending on the 'Linked Resources' preferences it copies the given files and folders to the
	 * destination or creates links or shows a dialog that lets the user choose. The current thread
	 * is halted while the resources are copied using a {@link WorkspaceModifyOperation}. This
	 * method should be called from the UI Thread.
	 *
	 * @param fileNames names of the files to copy
	 * @param destination destination to which files will be copied
	 * @param dropOperation the drop operation ({@link DND#DROP_NONE}, {@link DND#DROP_MOVE}
	 *            {@link DND#DROP_COPY}, {@link DND#DROP_LINK}, {@link DND#DROP_DEFAULT})
	 * @see WorkspaceModifyOperation
	 * @see Display#getThread()
	 * @see Thread#currentThread()
	 * @since 3.6
	 */
	public void copyOrLinkFiles(final String[] fileNames, IContainer destination, int dropOperation) {
		IPreferenceStore store= IDEWorkbenchPlugin.getDefault().getPreferenceStore();
		boolean targetIsVirtual= destination.isVirtual();
		String dndPreference= store.getString(targetIsVirtual ? IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_VIRTUAL_FOLDER_MODE : IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE);

		int mode= ImportTypeDialog.IMPORT_NONE;
		String variable= null;

		//check if resource linking is disabled
		if (ResourcesPlugin.getPlugin().getPluginPreferences().getBoolean(ResourcesPlugin.PREF_DISABLE_LINKING))
			mode= ImportTypeDialog.IMPORT_COPY;
		else {
			if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_PROMPT)) {
				ImportTypeDialog dialog= new ImportTypeDialog(messageShell, dropOperation, fileNames, destination);
				dialog.setResource(destination);
				if (dialog.open() == Window.OK) {
					mode= dialog.getSelection();
					variable= dialog.getVariable();
				}
			} else if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_MOVE_COPY)) {
				mode= ImportTypeDialog.IMPORT_COPY;
			} else if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_LINK)) {
				mode= ImportTypeDialog.IMPORT_LINK;
			} else if (dndPreference.equals(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_MODE_LINK_AND_VIRTUAL_FOLDER)) {
				mode= ImportTypeDialog.IMPORT_VIRTUAL_FOLDERS_AND_LINKS;
			}
		}

		switch (mode) {
			case ImportTypeDialog.IMPORT_COPY:
				copyFiles(fileNames, destination);
				break;
			case ImportTypeDialog.IMPORT_VIRTUAL_FOLDERS_AND_LINKS:
				if (variable != null)
					setRelativeVariable(variable);
				createVirtualFoldersAndLinks(fileNames, destination);
				break;
			case ImportTypeDialog.IMPORT_LINK:
				if (variable != null)
					setRelativeVariable(variable);
				linkFiles(fileNames, destination);
				break;
			case ImportTypeDialog.IMPORT_NONE:
				break;
		}

	}

	/**
	 * Copies the given files and folders to the destination. The current Thread is halted while the
	 * resources are copied using a WorkspaceModifyOperation. This method should be called from the
	 * UI Thread.
	 *
	 * @param fileNames names of the files to copy
	 * @param destination destination to which files will be copied
	 * @see WorkspaceModifyOperation
	 * @see Display#getThread()
	 * @see Thread#currentThread()
	 * @since 3.2
	 */
	public void copyFiles(final String[] fileNames, IContainer destination) {
		IFileStore[] stores = buildFileStores(fileNames);
		if (stores == null) {
			return;
		}

		copyFileStores(destination, stores, true, null);
	}

	/**
	 * Copies the given files and folders to the destination without forking a
	 * new Thread or blocking using a WorkspaceModifyOperation. It is
	 * recommended that this method only be called from a {@link WorkspaceJob}
	 * to avoid possible deadlock.
	 *
	 * @param fileNames
	 *            names of the files to copy
	 * @param destination
	 *            destination to which files will be copied
	 * @param monitor
	 *            the monitor that information will be sent to.
	 * @see WorkspaceModifyOperation
	 * @see WorkspaceJob
	 * @since 3.2
	 */
	public void copyFilesInCurrentThread(final String[] fileNames,
			IContainer destination, IProgressMonitor monitor) {
		IFileStore[] stores = buildFileStores(fileNames);
		if (stores == null) {
			return;
		}

		copyFileStores(destination, stores, false, monitor);
	}

	/**
	 * Build the collection of fileStores that map to fileNames. If any of them
	 * cannot be found then match then return null.
	 *
	 * @param fileNames
	 * @return IFileStore[]
	 */
	private IFileStore[] buildFileStores(final String[] fileNames) {
		IFileStore[] stores = new IFileStore[fileNames.length];
		for (int i = 0; i < fileNames.length; i++) {
			IFileStore store = IDEResourceInfoUtils.getFileStore(fileNames[i]);
			if (store == null) {
				reportFileInfoNotFound(fileNames[i]);
				return null;
			}
			stores[i] = store;
		}
		return stores;
	}

	/**
	 * Report that a file info could not be found.
	 *
	 * @param fileName
	 */
	private void reportFileInfoNotFound(final String fileName) {

		messageShell.getDisplay().syncExec(new Runnable() {
			@Override
			public void run() {
				ErrorDialog
						.openError(
								messageShell,
								getProblemsTitle(),
								NLS
										.bind(
												IDEWorkbenchMessages.CopyFilesAndFoldersOperation_infoNotFound,
												fileName), null);
			}
		});
	}

	/**
	 * Copies the given files and folders to the destination.
	 *
	 * @param stores
	 *            the file stores to copy
	 * @param destination
	 *            destination to which files will be copied
	 */
	private void copyFileStores(IContainer destination,
			final IFileStore[] stores, boolean fork, IProgressMonitor monitor) {
		// test files for existence separate from validate API
		// because an external file may not exist until the copy actually
		// takes place (e.g., WinZip contents).
		IStatus fileStatus = checkExist(stores);
		if (fileStatus.getSeverity() != IStatus.OK) {
			displayError(fileStatus);
			return;
		}
		String errorMsg = validateImportDestinationInternal(destination, stores);
		if (errorMsg != null) {
			displayError(errorMsg);
			return;
		}
		final IPath destinationPath = destination.getFullPath();

		if (fork) {
			WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
				@Override
				public void execute(IProgressMonitor monitor) {
					copyFileStores(stores, destinationPath, monitor);
				}
			};
			try {
				PlatformUI.getWorkbench().getProgressService().run(true, true,
						op);
			} catch (InterruptedException e) {
				return;
			} catch (InvocationTargetException exception) {
				display(exception);
			}
		} else {
			copyFileStores(stores, destinationPath, monitor);
		}

		// If errors occurred, open an Error dialog
		if (errorStatus != null) {
			displayError(errorStatus);
			errorStatus = null;
		}
	}

	/**
	 * Display the supplied status in an error dialog.
	 *
	 * @param status
	 *            The status to display
	 */
	private void displayError(final IStatus status) {
		messageShell.getDisplay().syncExec(new Runnable() {
			@Override
			public void run() {
				ErrorDialog.openError(messageShell, getProblemsTitle(), null,
						status);
			}
		});
	}

	/**
	 * Creates a file or folder handle for the source resource as if it were to
	 * be created in the destination container.
	 *
	 * @param destination
	 *            destination container
	 * @param source
	 *            source resource
	 * @return IResource file or folder handle, depending on the source type.
	 */
	IResource createLinkedResourceHandle(IContainer destination,
			IResource source) {
		IWorkspace workspace = destination.getWorkspace();
		IWorkspaceRoot workspaceRoot = workspace.getRoot();
		IPath linkPath = destination.getFullPath().append(source.getName());
		IResource linkHandle;

		if (source.getType() == IResource.FOLDER) {
			linkHandle = workspaceRoot.getFolder(linkPath);
		} else {
			linkHandle = workspaceRoot.getFile(linkPath);
		}
		return linkHandle;
	}

	/**
	 * Removes the given resource from the workspace.
	 *
	 * @param resource
	 *            resource to remove from the workspace
	 * @param monitor
	 *            a progress monitor for showing progress and for cancelation
	 * @return true the resource was deleted successfully false the resource was
	 *         not deleted because a CoreException occurred
	 */
	boolean delete(IResource resource, IProgressMonitor monitor) {
		boolean force = false; // don't force deletion of out-of-sync resources

		if (resource.getType() == IResource.PROJECT) {
			// if it's a project, ask whether content should be deleted too
			IProject project = (IProject) resource;
			try {
				project.delete(true, force, monitor);
			} catch (CoreException e) {
				recordError(e); // log error
				return false;
			}
		} else {
			// if it's not a project, just delete it
			int flags = IResource.KEEP_HISTORY;
			if (force) {
				flags = flags | IResource.FORCE;
			}
			try {
				resource.delete(flags, monitor);
			} catch (CoreException e) {
				recordError(e); // log error
				return false;
			}
		}
		return true;
	}

	/**
	 * Opens an error dialog to display the given message.
	 *
	 * @param message
	 *            the error message to show
	 */
	private void displayError(final String message) {
		messageShell.getDisplay().syncExec(new Runnable() {
			@Override
			public void run() {
				MessageDialog.openError(messageShell, getProblemsTitle(),
						message);
			}
		});
	}

	/**
	 * Returns the resource either casted to or adapted to an IFile.
	 *
	 * @param resource
	 *            resource to cast/adapt
	 * @return the resource either casted to or adapted to an IFile.
	 *         <code>null</code> if the resource does not adapt to IFile
	 */
	protected IFile getFile(IResource resource) {
		return Adapters.adapt(resource, IFile.class);
	}

	/**
	 * Returns java.io.File objects for the given file names.
	 *
	 * @param fileNames
	 *            files to return File object for.
	 * @return java.io.File objects for the given file names.
	 * @deprecated As of 3.3, this method is no longer in use anywhere in this
	 *             class and is only provided for backwards compatability with
	 *             subclasses of the receiver.
	 */
	@Deprecated
	protected File[] getFiles(String[] fileNames) {
		File[] files = new File[fileNames.length];

		for (int i = 0; i < fileNames.length; i++) {
			files[i] = new File(fileNames[i]);
		}
		return files;
	}

	/**
	 * Returns the resource either casted to or adapted to an IFolder.
	 *
	 * @param resource
	 *            resource to cast/adapt
	 * @return the resource either casted to or adapted to an IFolder.
	 *         <code>null</code> if the resource does not adapt to IFolder
	 */
	protected IFolder getFolder(IResource resource) {
		return Adapters.adapt(resource, IFolder.class);
	}

	/**
	 * Returns a new name for a copy of the resource at the given path in the
	 * given workspace.
	 *
	 * @param originalName
	 *            the full path of the resource
	 * @param workspace
	 *            the workspace
	 * @return the new full path for the copy, or <code>null</code> if the
	 *         resource should not be copied
	 */
	private IPath getNewNameFor(final IPath originalName,
			final IWorkspace workspace) {
		final IResource resource = workspace.getRoot().findMember(originalName);
		final IPath prefix = resource.getFullPath().removeLastSegments(1);
		final String returnValue[] = { "" }; //$NON-NLS-1$

		messageShell.getDisplay().syncExec(new Runnable() {
			@Override
			public void run() {
				IInputValidator validator = new IInputValidator() {
					@Override
					public String isValid(String string) {
						if (resource.getName().equals(string)) {
							return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_nameMustBeDifferent;
						}
						IStatus status = workspace.validateName(string,
								resource.getType());
						if (!status.isOK()) {
							return status.getMessage();
						}
						if (workspace.getRoot().exists(prefix.append(string))) {
							return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_nameExists;
						}
						return null;
					}
				};

				final String initial = getAutoNewNameFor(originalName, workspace).lastSegment().toString();
				InputDialog dialog = new InputDialog(
						messageShell,
						IDEWorkbenchMessages.CopyFilesAndFoldersOperation_inputDialogTitle,
						NLS
								.bind(
										IDEWorkbenchMessages.CopyFilesAndFoldersOperation_inputDialogMessage,
										resource.getName()), initial, validator) {

					@Override
					protected Control createContents(Composite parent) {
						Control contents= super.createContents(parent);
						int lastIndexOfDot= initial.lastIndexOf('.');
						if (resource instanceof IFile && lastIndexOfDot > 0) {
							getText().setSelection(0, lastIndexOfDot);
						}
						return contents;
					}
				};
				dialog.setBlockOnOpen(true);
				dialog.open();
				if (dialog.getReturnCode() == Window.CANCEL) {
					returnValue[0] = null;
				} else {
					returnValue[0] = dialog.getValue();
				}
			}
		});
		if (returnValue[0] == null) {
			throw new OperationCanceledException();
		}
		return prefix.append(returnValue[0]);
	}

	/**
	 * Returns the task title for this operation's progress dialog.
	 *
	 * @return the task title
	 */
	protected String getOperationTitle() {
		return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_operationTitle;
	}

	/**
	 * Returns the message for this operation's problems dialog.
	 *
	 * @return the problems message
	 */
	protected String getProblemsMessage() {
		return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_problemMessage;
	}

	/**
	 * Returns the title for this operation's problems dialog.
	 *
	 * @return the problems dialog title
	 */
	protected String getProblemsTitle() {
		return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyFailedTitle;
	}

	/**
	 * Returns whether the source file in a destination collision will be
	 * validateEdited together with the collision itself. Returns false. Should
	 * return true if the source file is to be deleted after the operation.
	 *
	 * @return boolean <code>true</code> if the source file in a destination
	 *         collision should be validateEdited. <code>false</code> if only
	 *         the destination should be validated.
	 */
	protected boolean getValidateConflictSource() {
		return false;
	}

	/**
	 * Returns whether the given resources are either both linked or both
	 * unlinked.
	 *
	 * @param source
	 *            source resource
	 * @param destination
	 *            destination resource
	 * @return boolean <code>true</code> if both resources are either linked
	 *         or unlinked. <code>false</code> otherwise.
	 */
	protected boolean homogenousResources(IResource source,
			IResource destination) {
		boolean isSourceLinked = source.isLinked();
		boolean isDestinationLinked = destination.isLinked();

		return (isSourceLinked && isDestinationLinked || isSourceLinked == false
				&& isDestinationLinked == false);
	}

	/**
	 * Returns whether the given resource is accessible. Files and folders are
	 * always considered accessible and a project is accessible if it is open.
	 *
	 * @param resource
	 *            the resource
	 * @return <code>true</code> if the resource is accessible, and
	 *         <code>false</code> if it is not
	 */
	private boolean isAccessible(IResource resource) {
		switch (resource.getType()) {
		case IResource.FILE:
			return true;
		case IResource.FOLDER:
			return true;
		case IResource.PROJECT:
			return ((IProject) resource).isOpen();
		default:
			return false;
		}
	}

	/**
	 * Returns whether any of the given source resources are being recopied to
	 * their current container.
	 *
	 * @param sourceResources
	 *            the source resources
	 * @param destination
	 *            the destination container
	 * @return <code>true</code> if at least one of the given source
	 *         resource's parent container is the same as the destination
	 */
	boolean isDestinationSameAsSource(IResource[] sourceResources,
			IContainer destination) {
		IPath destinationLocation = destination.getLocation();

		for (IResource resource : sourceResources) {
			if (resource.getParent().equals(destination)) {
				return true;
			} else if (destinationLocation != null) {
				// do thorough check to catch linked resources. Fixes bug 29913.
				IPath sourceLocation = resource.getLocation();
				IPath destinationResource = destinationLocation.append(resource.getName());
				if (sourceLocation != null
						&& sourceLocation.isPrefixOf(destinationResource)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Copies the given resources to the destination container with the given
	 * name.
	 * <p>
	 * Note: the destination container may need to be created prior to copying
	 * the resources.
	 * </p>
	 *
	 * @param resources
	 *            the resources to copy
	 * @param destination
	 *            the path of the destination container
	 * @param monitor
	 *            a progress monitor for showing progress and for cancelation
	 * @return <code>true</code> if the copy operation completed without
	 *         errors
	 */
	private boolean performCopy(IResource[] resources, IPath destination,
			IProgressMonitor monitor) {
		try {
			AbstractWorkspaceOperation op = getUndoableCopyOrMoveOperation(
					resources, destination);
			op.setModelProviderIds(getModelProviderIds());
			if (op instanceof CopyResourcesOperation) {
				CopyResourcesOperation copyMoveOp = (CopyResourcesOperation) op;
				copyMoveOp.setCreateVirtualFolders(createVirtualFoldersAndLinks);
				copyMoveOp.setCreateLinks(createLinks);
				copyMoveOp.setRelativeVariable(relativeVariable);
			}
			// If we are copying files and folders, do not execute the operation
			// in the undo history, since the creation of a new file is not
			// added to undo history and modification of a file is not added to
			// the same undo history and therefore a redo cannot be properly
			// done. Just execute it directly so it won't be added to the undo
			// history.
			op.execute(monitor, WorkspaceUndoUtil.getUIInfoAdapter(messageShell));
		} catch (ExecutionException e) {
			if (e.getCause() instanceof CoreException) {
				recordError((CoreException) e.getCause());
			} else {
				IDEWorkbenchPlugin.log(e.getMessage(), e);
				displayError(e.getMessage());
			}
			return false;
		}
		return true;
	}

	/**
	 * Individually copies the given resources to the specified destination
	 * container checking for name collisions. If a collision is detected, it is
	 * saved with a new name.
	 * <p>
	 * Note: the destination container may need to be created prior to copying
	 * the resources.
	 * </p>
	 *
	 * @param resources
	 *            the resources to copy
	 * @param destination
	 *            the path of the destination container
	 * @return <code>true</code> if the copy operation completed without
	 *         errors.
	 */
	private boolean performCopyWithAutoRename(IResource[] resources,
			IPath destination, IProgressMonitor monitor) {
		IWorkspace workspace = resources[0].getWorkspace();
		IPath[] destinationPaths = new IPath[resources.length];
		try {
			for (int i = 0; i < resources.length; i++) {
				IResource source = resources[i];
				destinationPaths[i] = destination.append(source.getName());
				if (source.getType() != IResource.FILE) {
					destinationPaths[i] = destinationPaths[i].addTrailingSeparator();
				}

				if (workspace.getRoot().exists(destinationPaths[i])) {
					destinationPaths[i] = getNewNameFor(destinationPaths[i],
							workspace);
				}
			}
			CopyResourcesOperation op = new CopyResourcesOperation(resources,
					destinationPaths,
					IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyTitle);
			op.setModelProviderIds(getModelProviderIds());
			// If we are copying files and folders, do not execute the operation
			// in the undo history, since the creation of a new file is not
			// added to undo history and modification of a file is not added to
			// the same undo history and therefore a redo cannot be properly
			// done. Just execute it directly so it won't be added to the undo
			// history.
			op.execute(monitor, WorkspaceUndoUtil.getUIInfoAdapter(messageShell));
		} catch (ExecutionException e) {
			if (e.getCause() instanceof CoreException) {
				recordError((CoreException) e.getCause());
			} else {
				IDEWorkbenchPlugin.log(e.getMessage(), e);
				displayError(e.getMessage());
			}
			return false;
		}
		return true;
	}

	/**
	 * Performs an import of the given stores into the provided container.
	 * Returns a status indicating if the import was successful.
	 *
	 * @param stores
	 *            stores that are to be imported
	 * @param target
	 *            container to which the import will be done
	 * @param monitor
	 *            a progress monitor for showing progress and for cancelation
	 */
	private void performFileImport(IFileStore[] stores, IContainer target,
			IProgressMonitor monitor) {
		IOverwriteQuery query = new IOverwriteQuery() {
			@Override
			public String queryOverwrite(String pathString) {
				if (alwaysOverwrite) {
					return ALL;
				}

				final String returnCode[] = { CANCEL };
				final String msg = NLS
						.bind(
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteQuestion,
								pathString);
				final String[] options = { IDialogConstants.YES_LABEL,
						IDialogConstants.YES_TO_ALL_LABEL,
						IDialogConstants.NO_LABEL,
						IDialogConstants.CANCEL_LABEL };
				messageShell.getDisplay().syncExec(new Runnable() {
					@Override
					public void run() {
						MessageDialog dialog = new MessageDialog(
								messageShell,
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_question,
								null, msg, MessageDialog.QUESTION, 0, options) {
							@Override
							protected int getShellStyle() {
								return super.getShellStyle() | SWT.SHEET;
							}
						};
						dialog.open();
						int returnVal = dialog.getReturnCode();
						String[] returnCodes = { YES, ALL, NO, CANCEL };
						returnCode[0] = returnVal == -1 ? CANCEL
								: returnCodes[returnVal];
					}
				});
				if (returnCode[0] == ALL) {
					alwaysOverwrite = true;
				} else if (returnCode[0] == CANCEL) {
					canceled = true;
				}
				return returnCode[0];
			}
		};

		ImportOperation op = new ImportOperation(target.getFullPath(),
				stores[0].getParent(), FileStoreStructureProvider.INSTANCE,
				query, Arrays.asList(stores));
		op.setContext(messageShell);
		op.setCreateContainerStructure(false);
		op.setVirtualFolders(createVirtualFoldersAndLinks);
		op.setCreateLinks(createLinks);
		op.setRelativeVariable(relativeVariable);
		try {
			op.run(monitor);
		} catch (InterruptedException e) {
			return;
		} catch (InvocationTargetException e) {
			if (e.getTargetException() instanceof CoreException) {
				displayError(((CoreException) e.getTargetException())
						.getStatus());
			} else {
				display(e);
			}
			return;
		}
		// Special case since ImportOperation doesn't throw a CoreException on
		// failure.
		IStatus status = op.getStatus();
		if (!status.isOK()) {
			if (errorStatus == null) {
				errorStatus = new MultiStatus(PlatformUI.PLUGIN_ID,
						IStatus.ERROR, getProblemsMessage(), null);
			}
			errorStatus.merge(status);
		}
	}

	/**
	 * Records the core exception to be displayed to the user once the action is
	 * finished.
	 *
	 * @param error
	 *            a <code>CoreException</code>
	 */
	private void recordError(CoreException error) {
		if (errorStatus == null) {
			errorStatus = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.ERROR,
					getProblemsMessage(), error);
		}

		errorStatus.merge(error.getStatus());
	}

	/**
	 * Checks whether the destination is valid for copying the source resources.
	 * <p>
	 * Note this method is for internal use only. It is not API.
	 * </p>
	 *
	 * @param destination
	 *            the destination container
	 * @param sourceResources
	 *            the source resources
	 * @return an error message, or <code>null</code> if the path is valid
	 */
	public String validateDestination(IContainer destination,
			IResource[] sourceResources) {
		if (!isAccessible(destination)) {
			return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationAccessError;
		}
		IContainer firstParent = null;
		URI destinationLocation = destination.getLocationURI();
		for (IResource sourceResource : sourceResources) {
			if (firstParent == null) {
				firstParent = sourceResource.getParent();
			} else if (firstParent.equals(sourceResource.getParent()) == false) {
				// Resources must have common parent. Fixes bug 33398.
				return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_parentNotEqual;
			}

			// verify that if the destination is a virtual folder, the resource must be
			// either a link or another virtual folder
			if (destination.isVirtual()) {
				if (!sourceResource.isLinked() && !sourceResource.isVirtual()
						&& !createLinks && !createVirtualFoldersAndLinks) {
					return NLS
							.bind(
									IDEWorkbenchMessages.CopyFilesAndFoldersOperation_sourceCannotBeCopiedIntoAVirtualFolder,
									sourceResource.getName());
				}
			}
			URI sourceLocation = sourceResource.getLocationURI();
			if (sourceLocation == null) {
				if (sourceResource.isLinked()) {
					// Don't allow copying linked resources with undefined path
					// variables. See bug 28754.
					return NLS
							.bind(
									IDEWorkbenchMessages.CopyFilesAndFoldersOperation_missingPathVariable,
									sourceResource.getName());
				}
				return NLS
						.bind(
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_resourceDeleted,
								sourceResource.getName());

			}
			if (!destination.isVirtual()) {
				if (sourceLocation.equals(destinationLocation)) {
					return NLS
							.bind(
									IDEWorkbenchMessages.CopyFilesAndFoldersOperation_sameSourceAndDest,
									sourceResource.getName());
				}
				// is the source a parent of the destination?
				if (new Path(sourceLocation.toString()).isPrefixOf(new Path(
						destinationLocation.toString()))) {
					return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationDescendentError;
				}
			}

			String linkedResourceMessage = validateLinkedResource(destination,
					sourceResource);
			if (linkedResourceMessage != null) {
				return linkedResourceMessage;
			}
		}
		return null;
	}

	/**
	 * Validates that the given source resources can be copied to the
	 * destination as decided by the VCM provider.
	 *
	 * @param destination
	 *            copy destination
	 * @param sourceResources
	 *            source resources
	 * @return <code>true</code> all files passed validation or there were no
	 *         files to validate. <code>false</code> one or more files did not
	 *         pass validation.
	 */
	private boolean validateEdit(IContainer destination,
			IResource[] sourceResources) {
		ArrayList copyFiles = new ArrayList();

		collectExistingReadonlyFiles(destination.getFullPath(),
				sourceResources, copyFiles);
		if (copyFiles.size() > 0) {
			IFile[] files = (IFile[]) copyFiles.toArray(new IFile[copyFiles
					.size()]);
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			IStatus status = workspace.validateEdit(files, messageShell);

			canceled = status.isOK() == false;
			return status.isOK();
		}
		return true;
	}

	/**
	 * Checks whether the destination is valid for copying the source files.
	 * <p>
	 * Note this method is for internal use only. It is not API.
	 * </p>
	 *
	 * @param destination
	 *            the destination container
	 * @param sourceNames
	 *            the source file names
	 * @return an error message, or <code>null</code> if the path is valid
	 */
	public String validateImportDestination(IContainer destination,
			String[] sourceNames) {

		IFileStore[] stores = new IFileStore[sourceNames.length];
		for (int i = 0; i < sourceNames.length; i++) {
			IFileStore store = IDEResourceInfoUtils
					.getFileStore(sourceNames[i]);
			if (store == null) {
				return NLS
						.bind(
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_infoNotFound,
								sourceNames[i]);
			}
			stores[i] = store;
		}
		return validateImportDestinationInternal(destination, stores);

	}

	/**
	 * Checks whether the destination is valid for copying the source file
	 * stores.
	 * <p>
	 * Note this method is for internal use only. It is not API.
	 * </p>
	 * <p>
	 * TODO Bug 117804. This method has been renamed to avoid a bug in the
	 * Eclipse compiler with regards to visibility and type resolution when
	 * linking.
	 * </p>
	 *
	 * @param destination
	 *            the destination container
	 * @param sourceStores
	 *            the source IFileStore
	 * @return an error message, or <code>null</code> if the path is valid
	 */
	private String validateImportDestinationInternal(IContainer destination,
			IFileStore[] sourceStores) {
		if (!isAccessible(destination))
			return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationAccessError;

		if (!destination.isVirtual()) {
			IFileStore destinationStore;
			try {
				destinationStore = EFS.getStore(destination.getLocationURI());
			} catch (CoreException exception) {
				IDEWorkbenchPlugin.log(exception.getLocalizedMessage(), exception);
				return NLS
						.bind(
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError,
								exception.getLocalizedMessage());
			}
			for (IFileStore fileStore : sourceStores) {
				IFileStore parentFileStore = fileStore.getParent();

				if (fileStore != null) {
					if (destinationStore.equals(fileStore)
							|| (parentFileStore != null && destinationStore
							.equals(parentFileStore))) {
						return NLS
								.bind(
										IDEWorkbenchMessages.CopyFilesAndFoldersOperation_importSameSourceAndDest,
										fileStore.getName());
					}
					// work around bug 16202. replacement for
					// sourcePath.isPrefixOf(destinationPath)
					if (fileStore.isParentOf(destinationStore)) {
						return IDEWorkbenchMessages.CopyFilesAndFoldersOperation_destinationDescendentError;
					}
				}
			}
		}
		return null;
	}

	/**
	 * Check if the destination is valid for the given source resource.
	 *
	 * @param destination
	 *            destination container of the operation
	 * @param source
	 *            source resource
	 * @return String error message or null if the destination is valid
	 */
	private String validateLinkedResource(IContainer destination,
			IResource source) {
		if ((source.isLinked() == false) || source.isVirtual()) {
			return null;
		}
		IWorkspace workspace = destination.getWorkspace();
		IResource linkHandle = createLinkedResourceHandle(destination, source);
		IStatus locationStatus = workspace.validateLinkLocationURI(linkHandle,
				source.getRawLocationURI());

		if (locationStatus.getSeverity() == IStatus.ERROR) {
			return locationStatus.getMessage();
		}
		IPath sourceLocation = source.getLocation();
		if (source.getProject().equals(destination.getProject()) == false
				&& source.getType() == IResource.FOLDER
				&& sourceLocation != null) {
			// prevent merging linked folders that point to the same
			// file system folder
			try {
				for (IResource resource : destination.members()) {
					if (sourceLocation.equals(resource.getLocation()) && source.getName().equals(resource.getName())) {
						return NLS
								.bind(
										IDEWorkbenchMessages.CopyFilesAndFoldersOperation_sameSourceAndDest,
										source.getName());
					}
				}
			} catch (CoreException exception) {
				displayError(NLS
						.bind(
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_internalError,
								exception.getMessage()));
			}
		}
		return null;
	}

	/**
	 * Returns whether moving all of the given source resources to the given
	 * destination container could be done without causing name collisions.
	 *
	 * @param destination
	 *            the destination container
	 * @param sourceResources
	 *            the list of resources
	 * @return <code>true</code> if there would be no name collisions, and
	 *         <code>false</code> if there would
	 */
	private IResource[] validateNoNameCollisions(IContainer destination,
			IResource[] sourceResources) {
		List copyItems = new ArrayList();
		IWorkspaceRoot workspaceRoot = destination.getWorkspace().getRoot();
		int overwrite = IDialogConstants.NO_ID;

		// Check to see if we would be overwriting a parent folder.
		// Cancel entire copy operation if we do.
		for (final IResource resource : sourceResources) {
			final IPath destinationPath = destination.getFullPath().append(
					resource.getName());
			final IPath sourcePath = resource.getFullPath();

			IResource newResource = workspaceRoot.findMember(destinationPath);
			if (newResource != null && destinationPath.isPrefixOf(sourcePath)) {
				displayError(NLS
						.bind(
								IDEWorkbenchMessages.CopyFilesAndFoldersOperation_overwriteProblem,
								destinationPath, sourcePath));

				canceled = true;
				return null;
			}
		}
		// Check for overwrite conflicts
		for (final IResource resource : sourceResources) {
			final IPath destinationPath = destination.getFullPath().append(
					resource.getName());

			IResource newResource = workspaceRoot.findMember(destinationPath);
			if (newResource != null) {
				if (overwrite != IDialogConstants.YES_TO_ALL_ID
						|| (newResource.getType() == IResource.FOLDER && homogenousResources(
								resource, destination) == false)) {
					overwrite = checkOverwrite(resource, newResource);
				}
				if (overwrite == IDialogConstants.YES_ID
						|| overwrite == IDialogConstants.YES_TO_ALL_ID) {
					copyItems.add(resource);
				} else if (overwrite == IDialogConstants.CANCEL_ID) {
					canceled = true;
					return null;
				}
			} else {
				copyItems.add(resource);
			}
		}
		return (IResource[]) copyItems.toArray(new IResource[copyItems.size()]);
	}

	private void copyResources(final IResource[] resources, final IPath destinationPath,
			final IResource[][] copiedResources, IProgressMonitor mon) {
		IResource[] copyResources = resources;

		// Fix for bug 31116. Do not provide a task name when
		// creating the task.
		SubMonitor subMonitor = SubMonitor.convert(mon, 100);
		subMonitor.setTaskName(getOperationTitle());
		subMonitor.worked(10); // show some initial progress

		// Checks only required if this is an exisiting container path.
		boolean copyWithAutoRename = false;
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		if (root.exists(destinationPath)) {
			IContainer container = (IContainer) root
					.findMember(destinationPath);
			// If we're copying to the source container then perform
			// auto-renames on all resources to avoid name collisions.
			if (isDestinationSameAsSource(copyResources, container)
					&& canPerformAutoRename()) {
				copyWithAutoRename = true;
			} else {
				// If no auto-renaming will be happening, check for
				// potential name collisions at the target resource
				copyResources = validateNoNameCollisions(container,
						copyResources);
				if (copyResources == null) {
					if (canceled) {
						return;
					}
					displayError(IDEWorkbenchMessages.CopyFilesAndFoldersOperation_nameCollision);
					return;
				}
				if (validateEdit(container, copyResources) == false) {
					return;
				}
			}
		}

		errorStatus = null;
		if (copyResources.length > 0) {
			if (copyWithAutoRename) {
				performCopyWithAutoRename(copyResources, destinationPath, subMonitor.split(90));
			} else {
				performCopy(copyResources, destinationPath, subMonitor.split(90));
			}
		}
		copiedResources[0] = copyResources;
	}

	private void copyFileStores(final IFileStore[] stores,
			final IPath destinationPath, IProgressMonitor monitor) {
		// Checks only required if this is an exisiting container path.
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		if (root.exists(destinationPath)) {
			IContainer container = (IContainer) root
					.findMember(destinationPath);

			performFileImport(stores, container, monitor);
		}
	}

	/**
	 * Returns the model provider ids that are known to the client that
	 * instantiated this operation.
	 *
	 * @return the model provider ids that are known to the client that
	 *         instantiated this operation.
	 * @since 3.2
	 */
	public String[] getModelProviderIds() {
		return modelProviderIds;
	}

	/**
	 * Sets the model provider ids that are known to the client that
	 * instantiated this operation. Any potential side effects reported by these
	 * models during validation will be ignored.
	 *
	 * @param modelProviderIds
	 *            the model providers known to the client who is using this
	 *            operation.
	 * @since 3.2
	 */
	public void setModelProviderIds(String[] modelProviderIds) {
		this.modelProviderIds = modelProviderIds;
	}

	/**
	 * Create virtual folders and links of the given files and folders to the
	 * destination. The current Thread is halted while the resources are copied
	 * using a WorkspaceModifyOperation. This method should be called from the
	 * UI Thread.
	 *
	 * @param fileNames
	 *            names of the files to copy
	 * @param destination
	 *            destination to which files will be copied
	 * @see WorkspaceModifyOperation
	 * @see Display#getThread()
	 * @see Thread#currentThread()
	 * @since 3.6
	 */
	public void createVirtualFoldersAndLinks(final String[] fileNames,
			IContainer destination) {
		IFileStore[] stores = buildFileStores(fileNames);
		if (stores == null) {
			return;
		}

		createVirtualFoldersAndLinks = true;
		copyFileStores(destination, stores, true, null);
	}

	/**
	 * Create links of the given files and folders to the destination. The
	 * current Thread is halted while the resources are copied using a
	 * WorkspaceModifyOperation. This method should be called from the UI
	 * Thread.
	 *
	 * @param fileNames
	 *            names of the files to copy
	 * @param destination
	 *            destination to which files will be copied
	 * @see WorkspaceModifyOperation
	 * @see Display#getThread()
	 * @see Thread#currentThread()
	 * @since 3.6
	 */
	public void linkFiles(final String[] fileNames, IContainer destination) {
		IFileStore[] stores = buildFileStores(fileNames);
		if (stores == null) {
			return;
		}

		createLinks = true;
		copyFileStores(destination, stores, true, null);
	}

	/**
	 * Set whether or not virtual folders and links will be created under the destination
	 * container.
	 *
	 * @param value
	 * @since 3.6
	 */
	public void setVirtualFolders(boolean value) {
		createVirtualFoldersAndLinks = value;
	}

	/**
	 * Set whether or not links will be created under the destination container.
	 *
	 * @param value
	 * @since 3.6
	 */
	public void setCreateLinks(boolean value) {
		createLinks = value;
	}

	/**
	 * Set a variable relative to which the links are created
	 *
	 * @param variable
	 * @since 3.6
	 */
	public void setRelativeVariable(String variable) {
		relativeVariable = variable;
	}

	/**
	 * Returns an AbstractWorkspaceOperation suitable for performing the move or
	 * copy operation that will move or copy the given resources to the given
	 * destination path.
	 *
	 * @param resources
	 *            the resources to be moved or copied
	 * @param destinationPath
	 *            the destination path to which the resources should be moved
	 * @return the operation that should be used to perform the move or cop
	 * @since 3.3
	 */
	protected AbstractWorkspaceOperation getUndoableCopyOrMoveOperation(
			IResource[] resources, IPath destinationPath) {
		return new CopyResourcesOperation(resources, destinationPath,
				IDEWorkbenchMessages.CopyFilesAndFoldersOperation_copyTitle);

	}
}
