package com.google.dart.tools.ui.internal.filesview;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
import org.eclipse.core.resources.mapping.ResourceChangeValidator;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ProjectLocationSelectionDialog;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
/**
* Implementation class to perform the actual copying of project resources from the clipboard when
* paste action is invoked.
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
* Copy from org.eclipse.ui.actions to return new {@link IProject}.
*
* @noextend This class is not intended to be subclassed by clients.
*/
@SuppressWarnings("restriction")
public class CopyProjectOperation {
/**
* Validates that the copy of the project will not have undesirable side effects.
*
* @param shell a shell
* @param project the project being copied
* @param newName the new name of the project
* @param modelProviderIds the model provider ids of models that are known to the client (and can
* hence be ignored)
* @return whether the operation should proceed
* @since 3.2
* @deprecated As of 3.3, validation is performed in the undoable operation executed by this
* operation.
*/
@Deprecated
protected static boolean validateCopy(Shell shell, IProject project, String newName,
String[] modelProviderIds) {
IResourceChangeDescriptionFactory factory = ResourceChangeValidator.getValidator().createDeltaFactory();
factory.copy(project, new Path(newName));
return IDE.promptToConfirm(
shell,
IDEWorkbenchMessages.CopyProjectAction_confirm,
NLS.bind(IDEWorkbenchMessages.CopyProjectAction_warning, project.getName()),
factory.getDelta(),
modelProviderIds,
false /* no need to sync exec */);
}
/**
* 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 parentShell;
private String[] modelProviderIds;
IProject newProject = null;
/**
* Create a new operation initialized with a shell.
*
* @param shell parent shell for error dialogs
*/
public CopyProjectOperation(Shell shell) {
parentShell = shell;
}
/**
* Paste a copy of the project on the clipboard to the workspace.
*
* @param project The project that is beign copied.
*/
public void copyProject(IProject project) {
errorStatus = null;
// Get the project name and location in a two element list
ProjectLocationSelectionDialog dialog = new ProjectLocationSelectionDialog(parentShell, project);
dialog.setTitle(IDEWorkbenchMessages.CopyProjectOperation_copyProject);
if (dialog.open() != Window.OK) {
return;
}
Object[] destinationPaths = dialog.getResult();
if (destinationPaths == null) {
return;
}
String newName = (String) destinationPaths[0];
URI newLocation = URIUtil.toURI((String) destinationPaths[1]);
boolean completed = performProjectCopy(project, newName, newLocation);
if (!completed) {
return; // not appropriate to show errors
}
// If errors occurred, open an Error dialog
if (errorStatus != null) {
ErrorDialog.openError(
parentShell,
IDEWorkbenchMessages.CopyProjectOperation_copyFailedTitle,
null,
errorStatus);
errorStatus = null;
}
}
/**
* 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;
}
/**
* Copies the project to the new values.
*
* @param project the project to copy
* @param projectName the name of the copy
* @param newLocation IPath
* @return <code>true</code> if the copy operation completed, and <code>false</code> if it was
* abandoned part way
*/
private boolean performProjectCopy(final IProject project, final String projectName,
final URI newLocation) {
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException {
org.eclipse.ui.ide.undo.CopyProjectOperation op = new org.eclipse.ui.ide.undo.CopyProjectOperation(
project,
projectName,
newLocation,
IDEWorkbenchMessages.CopyProjectOperation_copyProject);
op.setModelProviderIds(getModelProviderIds());
try {
PlatformUI.getWorkbench().getOperationSupport().getOperationHistory().execute(
op,
monitor,
WorkspaceUndoUtil.getUIInfoAdapter(parentShell));
// remember new project
Object[] affectedObjects = op.getAffectedObjects();
if (affectedObjects != null && affectedObjects.length == 1
&& affectedObjects[0] instanceof IProject) {
newProject = (IProject) affectedObjects[0];
}
} catch (final ExecutionException e) {
if (e.getCause() instanceof CoreException) {
recordError((CoreException) e.getCause());
} else {
throw new InvocationTargetException(e);
}
}
}
};
try {
new ProgressMonitorJobsDialog(parentShell).run(true, true, op);
} catch (InterruptedException e) {
return false;
} catch (InvocationTargetException e) {
final String message = e.getTargetException().getMessage();
parentShell.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openError(
parentShell,
IDEWorkbenchMessages.CopyProjectOperation_copyFailedTitle,
NLS.bind(IDEWorkbenchMessages.CopyProjectOperation_internalError, message));
}
});
return false;
}
return true;
}
/**
* 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,
IDEWorkbenchMessages.CopyProjectOperation_copyFailedMessage,
error);
}
errorStatus.merge(error.getStatus());
}
}