KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > operations > CVSOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.ui.operations;
12
13 import java.lang.reflect.InvocationTargetException JavaDoc;
14 import java.net.URL JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.core.resources.IResource;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.jface.action.Action;
22 import org.eclipse.jface.action.IAction;
23 import org.eclipse.jface.window.IShellProvider;
24 import org.eclipse.osgi.util.NLS;
25 import org.eclipse.swt.widgets.Shell;
26 import org.eclipse.team.core.TeamException;
27 import org.eclipse.team.internal.ccvs.core.CVSException;
28 import org.eclipse.team.internal.ccvs.core.CVSStatus;
29 import org.eclipse.team.internal.ccvs.ui.*;
30 import org.eclipse.team.internal.ccvs.ui.console.CVSOutputConsole;
31 import org.eclipse.team.internal.ui.dialogs.MultipleYesNoPrompter;
32 import org.eclipse.team.ui.TeamOperation;
33 import org.eclipse.ui.IWorkbenchPart;
34
35
36 /**
37  * This class is the abstract superclass for CVS operations. It provides
38  * error handling, prompting and other UI.
39  */

40 public abstract class CVSOperation extends TeamOperation implements IShellProvider {
41
42     private int statusCount;
43
44     private boolean involvesMultipleResources = false;
45
46     private List JavaDoc errors = new ArrayList JavaDoc(); // of IStatus
47

48     protected static final IStatus OK = Status.OK_STATUS;
49     
50     private Shell shell;
51
52     private MultipleYesNoPrompter prompter;
53     
54     protected CVSOperation(IWorkbenchPart part) {
55         super(part);
56     }
57     
58     /* (non-Javadoc)
59      * @see org.eclipse.team.internal.ui.actions.TeamOperation#getJobName()
60      */

61     protected String JavaDoc getJobName() {
62         return getTaskName();
63     }
64         
65     /* (non-Javadoc)
66      * @see org.eclipse.team.ui.TeamOperation#getOperationIcon()
67      */

68     protected URL JavaDoc getOperationIcon() {
69         return Platform.find(CVSUIPlugin.getPlugin().getBundle(), new Path(ICVSUIConstants.ICON_PATH + ICVSUIConstants.IMG_CVS_PERSPECTIVE));
70     }
71     
72     /* (non-Javadoc)
73      * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
74      */

75     public final void run(IProgressMonitor monitor) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
76         startOperation();
77         try {
78             monitor = Policy.monitorFor(monitor);
79             monitor.beginTask(null, 100);
80             monitor.setTaskName(getTaskName());
81             execute(Policy.subMonitorFor(monitor, 100));
82             endOperation();
83         } catch (CVSException e) {
84             // TODO: errors may not be empty (i.e. endOperation has not been executed)
85
throw new InvocationTargetException JavaDoc(e);
86         } finally {
87             monitor.done();
88         }
89     }
90     
91     protected void startOperation() {
92         statusCount = 0;
93         resetErrors();
94     }
95     
96     protected void endOperation() throws CVSException {
97         handleErrors((IStatus[]) errors.toArray(new IStatus[errors.size()]));
98     }
99
100     /**
101      * Subclasses must override this method to perform the operation.
102      * Clients should never call this method directly.
103      *
104      * @param monitor
105      * @throws CVSException
106      * @throws InterruptedException
107      */

108     protected abstract void execute(IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc;
109
110     protected void addError(IStatus status) {
111         if (status.isOK()) return;
112         if (isLastError(status)) return;
113         errors.add(status);
114     }
115
116     protected void collectStatus(IStatus status) {
117         if (isLastError(status)) return;
118         statusCount++;
119         if (!status.isOK()) addError(status);
120     }
121     
122     protected void resetErrors() {
123         errors.clear();
124         statusCount = 0;
125     }
126     
127     protected IStatus[] getErrors() {
128         return (IStatus[]) errors.toArray(new IStatus[errors.size()]);
129     }
130     
131     /**
132      * Get the last error taht occured. This can be useful when a method
133      * has a return type but wants to signal an error. The method in question
134      * can add the error using <code>addError(IStatus)</code> and return null.
135      * The caller can then query the error using this method. Also, <code>addError(IStatus)</code>
136      * will not add the error if it is already on the end of the list (using identity comparison)
137      * which allows the caller to still perform a <code>collectStatus(IStatus)</code>
138      * to get a valid operation count.
139      * @return
140      */

141     protected IStatus getLastError() {
142         Assert.isTrue(errors.size() > 0);
143         IStatus status = (IStatus)errors.get(errors.size() - 1);
144         return status;
145     }
146     
147     private boolean isLastError(IStatus status) {
148         return (errors.size() > 0 && getLastError() == status);
149     }
150     
151     /**
152      * Throw an exception that contains the given error status
153      * @param errors the errors that occurred during the operation
154      * @throws CVSException an exception that wraps the errors
155      */

156     protected void asException(IStatus[] errors) throws CVSException {
157         if (errors.length == 0) return;
158         if (errors.length == 1 && statusCount == 1) {
159             throw new CVSException(errors[0]);
160         }
161         MultiStatus result = new MultiStatus(CVSUIPlugin.ID, 0, getErrorMessage(errors, statusCount), null);
162         for (int i = 0; i < errors.length; i++) {
163             IStatus s = errors[i];
164             if (s.isMultiStatus()) {
165                 result.add(new CVSStatus(s.getSeverity(), s.getMessage(), s.getException()));
166                 result.addAll(s);
167             } else {
168                 result.add(s);
169             }
170         }
171         throw new CVSException(result);
172     }
173
174     /**
175      * Handle the errors that occured during an operation.
176      * The default is to throw an exception containing an status
177      * that are reportable (determined using <code>isReportableError</code>).
178      * @param errors the errors that occurred during the operation.
179      * Subclasses may override.
180      * @throws CVSException an exception if appropriate
181      */

182     protected final void handleErrors(IStatus[] errors) throws CVSException {
183         // We are only concerned with reportable errors.
184
// Others will appear in the console
185
List JavaDoc reportableErrors = new ArrayList JavaDoc();
186         for (int i = 0; i < errors.length; i++) {
187             IStatus status = errors[i];
188             if (isReportableError(status)) {
189                 reportableErrors.add(status);
190             } else if (status.isMultiStatus()) {
191                 IStatus[] children = status.getChildren();
192                 for (int j = 0; j < children.length; j++) {
193                     IStatus child = children[j];
194                     if (isReportableError(child)) {
195                         reportableErrors.add(status);
196                         break;
197                     }
198                 }
199             }
200         }
201         if (!reportableErrors.isEmpty())
202             asException((IStatus[]) reportableErrors.toArray(new IStatus[reportableErrors.size()]));
203     }
204
205     /**
206      * Return whether the given status is reportable. By default,
207      * only server errors are reportable. Subclasses may override.
208      * @param status an error status
209      * @return whether the status is reportable or should be ignored
210      */

211     protected boolean isReportableError(IStatus status) {
212         return status.getCode() == CVSStatus.SERVER_ERROR || CVSStatus.isInternalError(status) || status.getCode() == TeamException.UNABLE;
213     }
214
215     protected String JavaDoc getErrorMessage(IStatus[] failures, int totalOperations) {
216         return NLS.bind(CVSUIMessages.CVSOperation_0, new String JavaDoc[] { String.valueOf(failures.length), String.valueOf(totalOperations) });
217     }
218
219     /**
220      * This method prompts the user to overwrite an existing resource. It uses the
221      * <code>involvesMultipleResources</code> to determine what buttons to show.
222      * @param resource
223      * @param project
224      * @return
225      */

226     protected boolean promptToOverwrite(final String JavaDoc title, final String JavaDoc message, IResource resource) {
227         if (prompter == null) {
228             prompter = new MultipleYesNoPrompter(this, title, involvesMultipleResources(), false);
229         } else {
230             prompter.setTitle(title);
231         }
232         try {
233             return prompter.shouldInclude(message);
234         } catch (InterruptedException JavaDoc e) {
235             throw new OperationCanceledException();
236         }
237     }
238
239     /**
240      * This method is used by <code>promptToOverwrite</code> to determine which
241      * buttons to show in the prompter.
242      *
243      * @return
244      */

245     protected boolean involvesMultipleResources() {
246         return involvesMultipleResources;
247     }
248
249     public void setInvolvesMultipleResources(boolean b) {
250         involvesMultipleResources = b;
251     }
252
253     /**
254      * Return the string that is to be used as the task name for the operation
255      *
256      * @param remoteFolders
257      * @return
258      */

259     protected abstract String JavaDoc getTaskName();
260     
261     /**
262      * Return true if any of the accumulated status have a severity of ERROR
263      * @return
264      */

265     protected boolean errorsOccurred() {
266         for (Iterator JavaDoc iter = errors.iterator(); iter.hasNext();) {
267             IStatus status = (IStatus) iter.next();
268             if (isReportableError(status)) return true;
269             if (status.isMultiStatus()) {
270                 IStatus[] children = status.getChildren();
271                 for (int j = 0; j < children.length; j++) {
272                     IStatus child = children[j];
273                     if (isReportableError(child)) {
274                         return true;
275                     }
276                 }
277             }
278         }
279         return false;
280     }
281
282     /* (non-Javadoc)
283      * @see org.eclipse.team.internal.ui.actions.TeamOperation#getShell()
284      */

285     public Shell getShell() {
286         // Use the shell assigned to the operation if possible
287
if (shell != null && !shell.isDisposed()) {
288             return shell;
289         }
290         return super.getShell();
291     }
292     
293     /**
294      * Set the shell to be used by the operation. This only needs
295      * to be done if the operation does not have a workbench part.
296      * For example, if the operation is being run in a wizard.
297      * @param shell The shell to set.
298      */

299     public void setShell(Shell shell) {
300         this.shell = shell;
301     }
302     
303     /* (non-Javadoc)
304      * @see org.eclipse.team.ui.TeamOperation#canRunAsJob()
305      */

306     protected boolean canRunAsJob() {
307         // Put CVS jobs in the background by default.
308
return true;
309     }
310     
311     /* (non-Javadoc)
312      * @see org.eclipse.team.ui.TeamOperation#isSameFamilyAs(org.eclipse.team.ui.TeamOperation)
313      */

314     protected boolean isSameFamilyAs(TeamOperation operation) {
315         // Trat all CVS operations as a single family
316
return operation instanceof CVSOperation;
317     }
318     
319     /*
320      * Action to show the console that can be used by subclasses
321      * that wish to link the progress service to the console
322      */

323     protected IAction getShowConsoleAction() {
324         // Show the console as the goto action
325
return new Action(CVSUIMessages.CVSOperation_1) {
326             public void run() {
327                 CVSOutputConsole console = CVSUIPlugin.getPlugin().getConsole();
328                 if (console != null)
329                     console.show(true);
330             }
331             public String JavaDoc getToolTipText() {
332                 return CVSUIMessages.CVSOperation_2;
333             }
334         };
335     }
336 }
337
Popular Tags