KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > FileModificationValidator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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;
12
13 import java.lang.reflect.InvocationTargetException JavaDoc;
14 import java.net.URL JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IResource;
20 import org.eclipse.core.resources.team.FileModificationValidationContext;
21 import org.eclipse.core.runtime.*;
22 import org.eclipse.core.runtime.jobs.ISchedulingRule;
23 import org.eclipse.core.runtime.jobs.Job;
24 import org.eclipse.jface.dialogs.MessageDialog;
25 import org.eclipse.jface.operation.IRunnableWithProgress;
26 import org.eclipse.swt.widgets.Display;
27 import org.eclipse.swt.widgets.Shell;
28 import org.eclipse.team.core.TeamException;
29 import org.eclipse.team.core.synchronize.SyncInfo;
30 import org.eclipse.team.internal.ccvs.core.*;
31 import org.eclipse.team.internal.ccvs.core.client.Command;
32 import org.eclipse.team.internal.ccvs.ui.actions.EditorsAction;
33 import org.eclipse.team.internal.ccvs.ui.operations.UpdateOperation;
34 import org.eclipse.team.internal.ui.Utils;
35 import org.eclipse.ui.progress.IProgressConstants;
36
37 /**
38  * IFileModificationValidator that is plugged into the CVS Repository Provider
39  */

40 public class FileModificationValidator extends CVSCoreFileModificationValidator {
41     
42     public FileModificationValidator() {
43     }
44     
45     /* (non-Javadoc)
46      * @see org.eclipse.team.internal.ccvs.core.CVSCoreFileModificationValidator#edit(org.eclipse.core.resources.IFile[], org.eclipse.core.resources.team.FileModificationValidationContext)
47      */

48     protected IStatus edit(IFile[] readOnlyFiles, FileModificationValidationContext context) {
49         return edit(readOnlyFiles, getShell(context));
50     }
51     
52     private Shell getShell(FileModificationValidationContext context) {
53         if (context == null)
54             return null;
55         if (context.getShell() != null)
56             return (Shell)context.getShell();
57         return Utils.getShell(null, true);
58     }
59
60     private IStatus getStatus(InvocationTargetException JavaDoc e) {
61         Throwable JavaDoc target = e.getTargetException();
62         if (target instanceof TeamException) {
63             return ((TeamException) target).getStatus();
64         } else if (target instanceof CoreException) {
65             return ((CoreException) target).getStatus();
66         }
67         return new Status(IStatus.ERROR, CVSUIPlugin.ID, 0, CVSUIMessages.internal, target);
68     }
69         
70     private IStatus edit(final IFile[] files, final Shell shell) {
71         if (isPerformEdit()) {
72             try {
73                 if (shell != null && !promptToEditFiles(files, shell)) {
74                     // The user didn't want to edit.
75
// OK is returned but the file remains read-only
76
throw new InterruptedException JavaDoc();
77                 }
78                 
79                 // see if the file is up to date
80
if (shell != null && promptToUpdateFiles(files, shell)) {
81                     // The user wants to update the file
82
// Run the update in a runnable in order to get a busy cursor.
83
// This runnable is syncExeced in order to get a busy cursor
84
IRunnableWithProgress updateRunnable = new IRunnableWithProgress() {
85                         public void run(IProgressMonitor monitor) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
86                             performUpdate(files, monitor);
87                         }
88                     };
89                     if (isRunningInUIThread()) {
90                         // Only show a busy cursor if validate edit is blocking the UI
91
CVSUIPlugin.runWithProgress(shell, false, updateRunnable);
92                     } else {
93                         // We can't show a busy cursor (i.e., run in the UI thread)
94
// since this thread may hold locks and
95
// running an edit in the UI thread could try to obtain the
96
// same locks, resulting in a deadlock.
97
updateRunnable.run(new NullProgressMonitor());
98                     }
99                 }
100                 
101                 // Run the edit in a runnable in order to get a busy cursor.
102
// This runnable is syncExeced in order to get a busy cursor
103
IRunnableWithProgress editRunnable = new IRunnableWithProgress() {
104                     public void run(IProgressMonitor monitor) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
105                         try {
106                             performEdit(files, monitor);
107                         } catch (CVSException e) {
108                             new InvocationTargetException JavaDoc(e);
109                         }
110                     }
111                 };
112                 if (isRunningInUIThread()) {
113                     // Only show a busy cursor if validate edit is blocking the UI
114
CVSUIPlugin.runWithProgress(shell, false, editRunnable);
115                 } else {
116                     // We can't show a busy cursor (i.e., run in the UI thread)
117
// since this thread may hold locks and
118
// running an edit in the UI thread could try to obtain the
119
// same locks, resulting in a deadlock.
120
editRunnable.run(new NullProgressMonitor());
121                 }
122             } catch (InvocationTargetException JavaDoc e) {
123                 return getStatus(e);
124             } catch (InterruptedException JavaDoc e) {
125                 // Must return an error to indicate that it is not OK to edit the files
126
return new Status(IStatus.CANCEL, CVSUIPlugin.ID, 0, CVSUIMessages.FileModificationValidator_vetoMessage, null); //;
127
}
128         } else if (isPerformEditInBackground()) {
129             IStatus status = setWritable(files);
130             if (status.isOK())
131                 performEdit(files);
132             return status;
133         } else {
134             // Allow the files to be edited without notifying the server
135
return setWritable(files);
136         }
137
138         return Status.OK_STATUS;
139         
140     }
141     
142     protected void scheduleEditJob(Job job) {
143         job.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
144         job.setProperty(IProgressConstants.ICON_PROPERTY, getOperationIcon());
145         super.scheduleEditJob(job);
146     }
147     
148     private URL JavaDoc getOperationIcon() {
149         return FileLocator.find(CVSUIPlugin.getPlugin().getBundle(), new Path(ICVSUIConstants.ICON_PATH + ICVSUIConstants.IMG_CVS_PERSPECTIVE), null);
150     }
151     
152     private boolean isRunningInUIThread() {
153         return Display.getCurrent() != null;
154     }
155
156     private boolean promptToEditFiles(IFile[] files, Shell shell) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
157         if (files.length == 0)
158             return true;
159
160         if(isNeverPrompt())
161             return true;
162
163         // Contact the server to see if anyone else is editing the files
164
EditorsAction editors = fetchEditors(files, shell);
165         if (editors.isEmpty()) {
166             if (isAlwaysPrompt())
167                 return (promptEdit(shell));
168             return true;
169         } else {
170             return (editors.promptToEdit(shell));
171         }
172     }
173     
174     private boolean promptToUpdateFiles(IFile[] files, Shell shell) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
175         if (files.length == 0)
176             return false;
177         
178         if (isNeverUpdate())
179             return false;
180         
181         // Contact the server to see if the files are up-to-date
182
if (needsUpdate(files, new NullProgressMonitor())) {
183             if (isPromptUpdate())
184                 return (promptUpdate(shell));
185             return true; // auto update
186
}
187         
188         return false;
189     }
190
191     private boolean promptEdit(Shell shell) {
192         // Open the dialog using a sync exec (there are no guarantees that we
193
// were called from the UI thread
194
final boolean[] result = new boolean[] { false };
195         int flags = isRunningInUIThread() ? 0 : CVSUIPlugin.PERFORM_SYNC_EXEC;
196         CVSUIPlugin.openDialog(shell, new CVSUIPlugin.IOpenableInShell() {
197             public void open(Shell shell) {
198                 result[0] = MessageDialog.openQuestion(shell,CVSUIMessages.FileModificationValidator_3,CVSUIMessages.FileModificationValidator_4); //
199
}
200         }, flags);
201         return result[0];
202     }
203
204     private boolean promptUpdate(Shell shell) {
205         // Open the dialog using a sync exec (there are no guarantees that we
206
// were called from the UI thread
207
final boolean[] result = new boolean[] { false };
208         int flags = isRunningInUIThread() ? 0 : CVSUIPlugin.PERFORM_SYNC_EXEC;
209         CVSUIPlugin.openDialog(shell, new CVSUIPlugin.IOpenableInShell() {
210             public void open(Shell shell) {
211                 result[0] = MessageDialog.openQuestion(shell,CVSUIMessages.FileModificationValidator_5,CVSUIMessages.FileModificationValidator_6);
212             }
213         }, flags);
214         return result[0];
215     }
216
217     private boolean isPerformEdit() {
218         return ICVSUIConstants.PREF_EDIT_PROMPT_EDIT.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_ACTION));
219     }
220     
221     private boolean isPerformEditInBackground() {
222         return ICVSUIConstants.PREF_EDIT_IN_BACKGROUND.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_ACTION));
223     }
224     
225     private EditorsAction fetchEditors(IFile[] files, Shell shell) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
226         final EditorsAction editors = new EditorsAction(getProvider(files), files);
227         IRunnableWithProgress runnable = new IRunnableWithProgress() {
228             public void run(IProgressMonitor monitor) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
229                 editors.run(monitor);
230             }
231         };
232         if (isRunningInUIThread()) {
233             // Show a busy cursor if we are running in the UI thread
234
CVSUIPlugin.runWithProgress(shell, false, runnable);
235         } else {
236             // We can't show a busy cursor (i.e., run in the UI thread)
237
// since this thread may hold locks and
238
// running a CVS operation in the UI thread could try to obtain the
239
// same locks, resulting in a deadlock.
240
runnable.run(new NullProgressMonitor());
241         }
242         return editors;
243     }
244
245     private boolean isNeverPrompt() {
246         return ICVSUIConstants.PREF_EDIT_PROMPT_NEVER.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_PROMPT));
247     }
248
249     private boolean isAlwaysPrompt() {
250         return ICVSUIConstants.PREF_EDIT_PROMPT_ALWAYS.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_PROMPT));
251     }
252     
253     private boolean needsUpdate(IFile[] files, IProgressMonitor monitor) {
254         try {
255             CVSWorkspaceSubscriber subscriber = CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
256             subscriber.refresh(files, IResource.DEPTH_ZERO, monitor);
257             for (int i = 0; i < files.length; i++) {
258                 IFile file = files[i];
259                 SyncInfo info = subscriber.getSyncInfo(file);
260                 int direction = info.getKind() & SyncInfo.DIRECTION_MASK;
261                 if (direction == SyncInfo.CONFLICTING || direction == SyncInfo.INCOMING) {
262                     return true;
263                 }
264             }
265         } catch (TeamException e) {
266             // Log the exception and assume we don't need to update it
267
CVSProviderPlugin.log(e);
268         }
269         return false;
270     }
271     
272     private void performUpdate(IFile[] files, IProgressMonitor monitor) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
273         // TODO: This obtains the project rule which can cause a rule violation
274
new UpdateOperation(null /* no target part */, files, Command.NO_LOCAL_OPTIONS, null /* no tag */).run(monitor);
275     }
276     
277     private boolean isPromptUpdate() {
278         return ICVSUIConstants.PREF_UPDATE_PROMPT_IF_OUTDATED.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PROMPT));
279     }
280     
281     private boolean isNeverUpdate() {
282         return ICVSUIConstants.PREF_UPDATE_PROMPT_NEVER.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PROMPT));
283     }
284     
285     public ISchedulingRule validateEditRule(CVSResourceRuleFactory factory, IResource[] resources) {
286         if (!isNeverUpdate()) {
287             // We may need to perform an update so we need to obtain the lock on each project
288
Set JavaDoc projects = new HashSet JavaDoc();
289             for (int i = 0; i < resources.length; i++) {
290                 IResource resource = resources[i];
291                 if (isReadOnly(resource))
292                     projects.add(resource.getProject());
293             }
294             return createSchedulingRule(projects);
295         }
296         return internalValidateEditRule(factory, resources);
297     }
298 }
299
Popular Tags