KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > fix > CleanUpPostSaveListener


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.jdt.internal.corext.fix;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.LinkedList JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.text.edits.TextEdit;
21 import org.eclipse.text.edits.UndoEdit;
22
23 import org.eclipse.core.runtime.Assert;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IPath;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.NullProgressMonitor;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.core.runtime.SubProgressMonitor;
31 import org.eclipse.core.runtime.preferences.DefaultScope;
32 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
33 import org.eclipse.core.runtime.preferences.InstanceScope;
34
35 import org.eclipse.core.filebuffers.FileBuffers;
36 import org.eclipse.core.filebuffers.ITextFileBuffer;
37 import org.eclipse.core.filebuffers.ITextFileBufferManager;
38 import org.eclipse.core.filebuffers.LocationKind;
39
40 import org.eclipse.core.resources.IFile;
41 import org.eclipse.core.resources.IProject;
42 import org.eclipse.core.resources.ProjectScope;
43
44 import org.eclipse.swt.widgets.Shell;
45
46 import org.eclipse.jface.dialogs.Dialog;
47 import org.eclipse.jface.window.Window;
48
49 import org.eclipse.jface.text.BadLocationException;
50 import org.eclipse.jface.text.IDocument;
51 import org.eclipse.jface.text.IDocumentExtension4;
52
53 import org.eclipse.ui.PlatformUI;
54
55 import org.eclipse.ltk.core.refactoring.Change;
56 import org.eclipse.ltk.core.refactoring.CompositeChange;
57 import org.eclipse.ltk.core.refactoring.IRefactoringCoreStatusCodes;
58 import org.eclipse.ltk.core.refactoring.IUndoManager;
59 import org.eclipse.ltk.core.refactoring.NullChange;
60 import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
61 import org.eclipse.ltk.core.refactoring.RefactoringCore;
62 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
63 import org.eclipse.ltk.core.refactoring.TextFileChange;
64 import org.eclipse.ltk.ui.refactoring.RefactoringUI;
65
66 import org.eclipse.jdt.core.ICompilationUnit;
67 import org.eclipse.jdt.core.IJavaProject;
68 import org.eclipse.jdt.core.dom.ASTParser;
69 import org.eclipse.jdt.core.dom.CompilationUnit;
70
71 import org.eclipse.jdt.internal.corext.fix.CleanUpRefactoring.CleanUpChange;
72 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
73 import org.eclipse.jdt.internal.corext.util.Messages;
74
75 import org.eclipse.jdt.ui.JavaUI;
76
77 import org.eclipse.jdt.internal.ui.actions.ActionUtil;
78 import org.eclipse.jdt.internal.ui.fix.ICleanUp;
79 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
80 import org.eclipse.jdt.internal.ui.javaeditor.saveparticipant.IPostSaveListener;
81
82 public class CleanUpPostSaveListener implements IPostSaveListener {
83     
84     private static class CleanUpSaveUndo extends TextFileChange {
85
86         private final IFile fFile;
87         private final UndoEdit[] fUndos;
88         private final long fDocumentStamp;
89         private final long fFileStamp;
90
91         public CleanUpSaveUndo(String JavaDoc name, IFile file, UndoEdit[] undos, long documentStamp, long fileStamp) {
92             super(name, file);
93             Assert.isNotNull(undos);
94             
95             fDocumentStamp= documentStamp;
96             fFileStamp= fileStamp;
97             fFile= file;
98             fUndos= undos;
99         }
100
101         public final boolean needsSaving() {
102             return true;
103         }
104
105         /**
106          * {@inheritDoc}
107          */

108         public Change perform(IProgressMonitor pm) throws CoreException {
109             if (isValid(pm).hasFatalError())
110                 return new NullChange();
111             
112             if (pm == null)
113                 pm= new NullProgressMonitor();
114             
115             ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
116             pm.beginTask("", 2); //$NON-NLS-1$
117
ITextFileBuffer buffer= null;
118             try {
119                 manager.connect(fFile.getFullPath(), LocationKind.IFILE, new SubProgressMonitor(pm, 1));
120                 buffer= manager.getTextFileBuffer(fFile.getFullPath(), LocationKind.IFILE);
121                 IDocument document= buffer.getDocument();
122                 
123                 long oldFileValue= fFile.getModificationStamp();
124                 long oldDocValue;
125                 if (document instanceof IDocumentExtension4) {
126                     oldDocValue= ((IDocumentExtension4)document).getModificationStamp();
127                 } else {
128                     oldDocValue= oldFileValue;
129                 }
130
131                 // perform the changes
132
LinkedList JavaDoc list= new LinkedList JavaDoc();
133                 for (int index= 0; index < fUndos.length; index++) {
134                     UndoEdit edit= fUndos[index];
135                     UndoEdit redo= edit.apply(document, TextEdit.CREATE_UNDO);
136                     list.addFirst(redo);
137                 }
138
139                 boolean stampSetted= false;
140                 
141                 if (document instanceof IDocumentExtension4 && fDocumentStamp != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP) {
142                     try {
143                         ((IDocumentExtension4)document).replace(0, 0, "", fDocumentStamp); //$NON-NLS-1$
144
stampSetted= true;
145                     } catch (BadLocationException e) {
146                         String JavaDoc message= e.getMessage();
147                         if (message == null)
148                             message= "BadLocationException"; //$NON-NLS-1$
149
throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IRefactoringCoreStatusCodes.BAD_LOCATION, message, e));
150                     }
151                 }
152                 
153                 buffer.commit(pm, false);
154                 if (!stampSetted) {
155                     fFile.revertModificationStamp(fFileStamp);
156                 }
157                 
158                 return new CleanUpSaveUndo(getName(), fFile, ((UndoEdit[]) list.toArray(new UndoEdit[list.size()])), oldDocValue, oldFileValue);
159             } catch (BadLocationException e) {
160                 String JavaDoc message= e.getMessage();
161                 if (message == null)
162                     message= "BadLocationException"; //$NON-NLS-1$
163
throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IRefactoringCoreStatusCodes.BAD_LOCATION, message, e));
164             } finally {
165                 if (buffer != null)
166                     manager.disconnect(fFile.getFullPath(), LocationKind.IFILE, new SubProgressMonitor(pm, 1));
167             }
168         }
169     }
170
171     public static final String JavaDoc POSTSAVELISTENER_ID= "org.eclipse.jdt.ui.postsavelistener.cleanup"; //$NON-NLS-1$
172
private static final String JavaDoc WARNING_VALUE= "warning"; //$NON-NLS-1$
173
private static final String JavaDoc ERROR_VALUE= "error"; //$NON-NLS-1$
174

175     /**
176      * {@inheritDoc}
177      */

178     public void saved(ICompilationUnit unit, IProgressMonitor monitor) throws CoreException {
179         if (monitor == null)
180             monitor= new NullProgressMonitor();
181         
182         monitor.beginTask(getName(), IProgressMonitor.UNKNOWN);
183         
184         try {
185             if (!ActionUtil.isOnBuildPath(unit))
186                 return;
187             
188             IProject project= unit.getJavaProject().getProject();
189             Map JavaDoc settings= CleanUpPreferenceUtil.loadSaveParticipantOptions(new ProjectScope(project));
190             if (settings == null) {
191                 IEclipsePreferences contextNode= new InstanceScope().getNode(JavaUI.ID_PLUGIN);
192                 String JavaDoc id= contextNode.get(CleanUpConstants.CLEANUP_ON_SAVE_PROFILE, null);
193                 if (id == null) {
194                     id= new DefaultScope().getNode(JavaUI.ID_PLUGIN).get(CleanUpConstants.CLEANUP_ON_SAVE_PROFILE, CleanUpConstants.DEFAULT_SAVE_PARTICIPANT_PROFILE);
195                 }
196                 throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, Messages.format(FixMessages.CleanUpPostSaveListener_unknown_profile_error_message, id)));
197             }
198             
199             ICleanUp[] cleanUps;
200             if (CleanUpConstants.TRUE.equals(settings.get(CleanUpConstants.CLEANUP_ON_SAVE_ADDITIONAL_OPTIONS))) {
201                 cleanUps= CleanUpRefactoring.createCleanUps(settings);
202             } else {
203                 HashMap JavaDoc filteredSettins= new HashMap JavaDoc();
204                 filteredSettins.put(CleanUpConstants.FORMAT_SOURCE_CODE, settings.get(CleanUpConstants.FORMAT_SOURCE_CODE));
205                 filteredSettins.put(CleanUpConstants.ORGANIZE_IMPORTS, settings.get(CleanUpConstants.ORGANIZE_IMPORTS));
206                 cleanUps= CleanUpRefactoring.createCleanUps(filteredSettins);
207             }
208                         
209             long oldFileValue= unit.getResource().getModificationStamp();
210             long oldDocValue= getDocumentStamp((IFile)unit.getResource(), new SubProgressMonitor(monitor, 2));
211             
212             CompositeChange result= new CompositeChange(FixMessages.CleanUpPostSaveListener_SaveAction_ChangeName);
213             LinkedList JavaDoc undoEdits= new LinkedList JavaDoc();
214             
215             IUndoManager manager= RefactoringCore.getUndoManager();
216             
217             try {
218                 manager.aboutToPerformChange(result);
219                 
220                 do {
221                     RefactoringStatus preCondition= new RefactoringStatus();
222                     for (int i= 0; i < cleanUps.length; i++) {
223                         RefactoringStatus conditions= cleanUps[i].checkPreConditions(unit.getJavaProject(), new ICompilationUnit[] {unit}, new SubProgressMonitor(monitor, 5));
224                         preCondition.merge(conditions);
225                     }
226                     if (showStatus(preCondition) != Window.OK)
227                         return;
228                     
229                     Map JavaDoc options= new HashMap JavaDoc();
230                     for (int i= 0; i < cleanUps.length; i++) {
231                         Map JavaDoc map= cleanUps[i].getRequiredOptions();
232                         if (map != null) {
233                             options.putAll(map);
234                         }
235                     }
236                         
237                     CompilationUnit ast= null;
238                     if (requiresAST(cleanUps, unit)) {
239                         ast= createAst(unit, options, new SubProgressMonitor(monitor, 10));
240                     }
241                     
242                     List JavaDoc undoneCleanUps= new ArrayList JavaDoc();
243                     CleanUpChange change= CleanUpRefactoring.calculateChange(ast, unit, cleanUps, undoneCleanUps);
244                     
245                     RefactoringStatus postCondition= new RefactoringStatus();
246                     for (int i= 0; i < cleanUps.length; i++) {
247                         RefactoringStatus conditions= cleanUps[i].checkPostConditions(new SubProgressMonitor(monitor, 1));
248                         postCondition.merge(conditions);
249                     }
250                     if (showStatus(postCondition) != Window.OK)
251                         return;
252                     
253                     if (change != null) {
254                         result.add(change);
255                         
256                         change.setSaveMode(TextFileChange.LEAVE_DIRTY);
257                         change.initializeValidationData(new NullProgressMonitor());
258                         
259                         PerformChangeOperation performChangeOperation= RefactoringUI.createUIAwareChangeOperation(change);
260                         performChangeOperation.setSchedulingRule(unit.getSchedulingRule());
261                         
262                         performChangeOperation.run(new SubProgressMonitor(monitor, 5));
263                         
264                         performChangeOperation.getUndoChange();
265                         undoEdits.addFirst(change.getUndoEdit());
266                     }
267                     
268                     cleanUps= (ICleanUp[])undoneCleanUps.toArray(new ICleanUp[undoneCleanUps.size()]);
269                 } while (cleanUps.length > 0);
270             } finally {
271                 manager.changePerformed(result, true);
272             }
273             
274             if (undoEdits.size() > 0) {
275                 UndoEdit[] undoEditArray= (UndoEdit[])undoEdits.toArray(new UndoEdit[undoEdits.size()]);
276                 CleanUpSaveUndo undo= new CleanUpSaveUndo(result.getName(), (IFile)unit.getResource(), undoEditArray, oldDocValue, oldFileValue);
277                 undo.initializeValidationData(new NullProgressMonitor());
278                 manager.addUndo(result.getName(), undo);
279             }
280         } finally {
281             monitor.done();
282         }
283     }
284
285     private int showStatus(RefactoringStatus status) {
286         if (!status.hasError())
287             return Window.OK;
288
289         Shell shell= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
290         
291         Dialog dialog= RefactoringUI.createRefactoringStatusDialog(status, shell, "", false); //$NON-NLS-1$
292
return dialog.open();
293     }
294
295     private long getDocumentStamp(IFile file, IProgressMonitor monitor) throws CoreException {
296         final ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
297         final IPath path= file.getFullPath();
298
299         monitor.beginTask("", 2); //$NON-NLS-1$
300

301         ITextFileBuffer buffer= null;
302         try {
303             manager.connect(path, LocationKind.IFILE, new SubProgressMonitor(monitor, 1));
304             buffer= manager.getTextFileBuffer(path, LocationKind.IFILE);
305             IDocument document= buffer.getDocument();
306             
307             if (document instanceof IDocumentExtension4) {
308                 return ((IDocumentExtension4)document).getModificationStamp();
309             } else {
310                 return file.getModificationStamp();
311             }
312         } finally {
313             if (buffer != null)
314                 manager.disconnect(path, LocationKind.IFILE, new SubProgressMonitor(monitor, 1));
315             monitor.done();
316         }
317     }
318
319     private boolean requiresAST(ICleanUp[] cleanUps, ICompilationUnit unit) throws CoreException {
320         for (int i= 0; i < cleanUps.length; i++) {
321             if (cleanUps[i].requireAST(unit))
322                 return true;
323         }
324         
325         return false;
326     }
327
328     private CompilationUnit createAst(ICompilationUnit unit, Map JavaDoc cleanUpOptions, IProgressMonitor monitor) {
329         IJavaProject project= unit.getJavaProject();
330         if (compatibleOptions(project, cleanUpOptions)) {
331             CompilationUnit ast= ASTProvider.getASTProvider().getAST(unit, ASTProvider.WAIT_NO, monitor);
332             if (ast != null)
333                 return ast;
334         }
335         
336         ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
337         parser.setResolveBindings(true);
338         parser.setProject(project);
339         parser.setSource(unit);
340         Map JavaDoc compilerOptions= RefactoringASTParser.getCompilerOptions(unit.getJavaProject());
341         compilerOptions.putAll(cleanUpOptions);
342         parser.setCompilerOptions(compilerOptions);
343         
344         return (CompilationUnit)parser.createAST(monitor);
345     }
346     
347     private boolean compatibleOptions(IJavaProject project, Map JavaDoc cleanUpOptions) {
348         if (cleanUpOptions.size() == 0)
349             return true;
350         
351         Map JavaDoc projectOptions= project.getOptions(true);
352         
353         for (Iterator JavaDoc iterator= cleanUpOptions.keySet().iterator(); iterator.hasNext();) {
354             String JavaDoc key= (String JavaDoc)iterator.next();
355             String JavaDoc projectOption= (String JavaDoc)projectOptions.get(key);
356             String JavaDoc cleanUpOption= (String JavaDoc)cleanUpOptions.get(key);
357             if (!strongerEquals(projectOption, cleanUpOption))
358                 return false;
359         }
360         
361         return true;
362     }
363
364     private boolean strongerEquals(String JavaDoc projectOption, String JavaDoc cleanUpOption) {
365         if (projectOption == null)
366             return false;
367         
368         if (ERROR_VALUE.equals(cleanUpOption)) {
369             return ERROR_VALUE.equals(projectOption);
370         } else if (WARNING_VALUE.equals(cleanUpOption)) {
371             return ERROR_VALUE.equals(projectOption) || WARNING_VALUE.equals(projectOption);
372         }
373         
374         return false;
375     }
376
377     /**
378      * {@inheritDoc}
379      */

380     public String JavaDoc getName() {
381         return FixMessages.CleanUpPostSaveListener_name;
382     }
383     
384     /**
385      * {@inheritDoc}
386      */

387     public String JavaDoc getId() {
388         return POSTSAVELISTENER_ID;
389     }
390     
391 }
392
Popular Tags