001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.actions;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.net.URI;
014:
015: import org.eclipse.core.commands.ExecutionException;
016: import org.eclipse.core.filesystem.URIUtil;
017: import org.eclipse.core.resources.IProject;
018: import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
019: import org.eclipse.core.resources.mapping.ResourceChangeValidator;
020: import org.eclipse.core.runtime.CoreException;
021: import org.eclipse.core.runtime.IProgressMonitor;
022: import org.eclipse.core.runtime.IStatus;
023: import org.eclipse.core.runtime.MultiStatus;
024: import org.eclipse.core.runtime.Path;
025: import org.eclipse.jface.dialogs.ErrorDialog;
026: import org.eclipse.jface.dialogs.MessageDialog;
027: import org.eclipse.jface.operation.IRunnableWithProgress;
028: import org.eclipse.jface.window.Window;
029: import org.eclipse.osgi.util.NLS;
030: import org.eclipse.swt.widgets.Shell;
031: import org.eclipse.ui.PlatformUI;
032: import org.eclipse.ui.dialogs.ProjectLocationSelectionDialog;
033: import org.eclipse.ui.ide.IDE;
034: import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
035: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
036: import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
037:
038: /**
039: * Implementation class to perform the actual copying of project resources from
040: * the clipboard when paste action is invoked.
041: * <p>
042: * This class may be instantiated; it is not intended to be subclassed.
043: * </p>
044: */
045: public class CopyProjectOperation {
046:
047: /**
048: * Status containing the errors detected when running the operation or
049: * <code>null</code> if no errors detected.
050: */
051: private MultiStatus errorStatus;
052:
053: /**
054: * The parent shell used to show any dialogs.
055: */
056: private Shell parentShell;
057:
058: private String[] modelProviderIds;
059:
060: /**
061: * Validates that the copy of the project will not have undesirable side
062: * effects.
063: *
064: * @param shell
065: * a shell
066: * @param project
067: * the project being copied
068: * @param newName
069: * the new name of the project
070: * @param modelProviderIds
071: * the model provider ids of models that are known to the client
072: * (and can hence be ignored)
073: * @return whether the operation should proceed
074: * @since 3.2
075: * @deprecated As of 3.3, validation is performed in the undoable operation
076: * executed by this operation.
077: */
078: protected static boolean validateCopy(Shell shell,
079: IProject project, String newName, String[] modelProviderIds) {
080: IResourceChangeDescriptionFactory factory = ResourceChangeValidator
081: .getValidator().createDeltaFactory();
082: factory.copy(project, new Path(newName));
083: return IDE.promptToConfirm(shell,
084: IDEWorkbenchMessages.CopyProjectAction_confirm,
085: NLS.bind(
086: IDEWorkbenchMessages.CopyProjectAction_warning,
087: project.getName()), factory.getDelta(),
088: modelProviderIds, false /* no need to sync exec */);
089: }
090:
091: /**
092: * Create a new operation initialized with a shell.
093: *
094: * @param shell
095: * parent shell for error dialogs
096: */
097: public CopyProjectOperation(Shell shell) {
098: parentShell = shell;
099: }
100:
101: /**
102: * Paste a copy of the project on the clipboard to the workspace.
103: *
104: * @param project
105: * The project that is beign copied.
106: */
107: public void copyProject(IProject project) {
108: errorStatus = null;
109:
110: // Get the project name and location in a two element list
111: ProjectLocationSelectionDialog dialog = new ProjectLocationSelectionDialog(
112: parentShell, project);
113: dialog
114: .setTitle(IDEWorkbenchMessages.CopyProjectOperation_copyProject);
115: if (dialog.open() != Window.OK) {
116: return;
117: }
118:
119: Object[] destinationPaths = dialog.getResult();
120: if (destinationPaths == null) {
121: return;
122: }
123:
124: String newName = (String) destinationPaths[0];
125: URI newLocation = URIUtil.toURI((String) destinationPaths[1]);
126:
127: boolean completed = performProjectCopy(project, newName,
128: newLocation);
129:
130: if (!completed) {
131: return; // not appropriate to show errors
132: }
133:
134: // If errors occurred, open an Error dialog
135: if (errorStatus != null) {
136: ErrorDialog
137: .openError(
138: parentShell,
139: IDEWorkbenchMessages.CopyProjectOperation_copyFailedTitle,
140: null, errorStatus);
141: errorStatus = null;
142: }
143: }
144:
145: /**
146: * Copies the project to the new values.
147: *
148: * @param project
149: * the project to copy
150: * @param projectName
151: * the name of the copy
152: * @param newLocation
153: * IPath
154: * @return <code>true</code> if the copy operation completed, and
155: * <code>false</code> if it was abandoned part way
156: */
157: private boolean performProjectCopy(final IProject project,
158: final String projectName, final URI newLocation) {
159: IRunnableWithProgress op = new IRunnableWithProgress() {
160: public void run(IProgressMonitor monitor)
161: throws InvocationTargetException {
162: org.eclipse.ui.ide.undo.CopyProjectOperation op = new org.eclipse.ui.ide.undo.CopyProjectOperation(
163: project,
164: projectName,
165: newLocation,
166: IDEWorkbenchMessages.CopyProjectOperation_copyProject);
167: op.setModelProviderIds(getModelProviderIds());
168: try {
169: PlatformUI
170: .getWorkbench()
171: .getOperationSupport()
172: .getOperationHistory()
173: .execute(
174: op,
175: monitor,
176: WorkspaceUndoUtil
177: .getUIInfoAdapter(parentShell));
178: } catch (final ExecutionException e) {
179: if (e.getCause() instanceof CoreException) {
180: recordError((CoreException) e.getCause());
181: } else {
182: throw new InvocationTargetException(e);
183: }
184: }
185: }
186: };
187:
188: try {
189: new ProgressMonitorJobsDialog(parentShell).run(true, true,
190: op);
191: } catch (InterruptedException e) {
192: return false;
193: } catch (InvocationTargetException e) {
194: final String message = e.getTargetException().getMessage();
195: parentShell.getDisplay().syncExec(new Runnable() {
196: public void run() {
197: MessageDialog
198: .openError(
199: parentShell,
200: IDEWorkbenchMessages.CopyProjectOperation_copyFailedTitle,
201: NLS
202: .bind(
203: IDEWorkbenchMessages.CopyProjectOperation_internalError,
204: message));
205: }
206: });
207: return false;
208: }
209:
210: return true;
211: }
212:
213: /**
214: * Records the core exception to be displayed to the user
215: * once the action is finished.
216: *
217: * @param error a <code>CoreException</code>
218: */
219: private void recordError(CoreException error) {
220:
221: if (errorStatus == null) {
222: errorStatus = new MultiStatus(
223: PlatformUI.PLUGIN_ID,
224: IStatus.ERROR,
225: IDEWorkbenchMessages.CopyProjectOperation_copyFailedMessage,
226: error);
227: }
228:
229: errorStatus.merge(error.getStatus());
230: }
231:
232: /**
233: * Returns the model provider ids that are known to the client
234: * that instantiated this operation.
235: *
236: * @return the model provider ids that are known to the client
237: * that instantiated this operation.
238: * @since 3.2
239: */
240: public String[] getModelProviderIds() {
241: return modelProviderIds;
242: }
243:
244: /**
245: * Sets the model provider ids that are known to the client that
246: * instantiated this operation. Any potential side effects reported by these
247: * models during validation will be ignored.
248: *
249: * @param modelProviderIds
250: * the model providers known to the client who is using this
251: * operation.
252: * @since 3.2
253: */
254: public void setModelProviderIds(String[] modelProviderIds) {
255: this.modelProviderIds = modelProviderIds;
256: }
257: }
|