KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ltk > internal > core > refactoring > history > RefactoringHistoryManager


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.ltk.internal.core.refactoring.history;
12
13 import java.io.BufferedInputStream JavaDoc;
14 import java.io.BufferedOutputStream JavaDoc;
15 import java.io.BufferedReader JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStream JavaDoc;
18 import java.io.InputStreamReader JavaDoc;
19 import java.io.OutputStream JavaDoc;
20 import java.io.OutputStreamWriter JavaDoc;
21 import java.io.PrintWriter JavaDoc;
22 import java.io.Writer JavaDoc;
23 import java.nio.charset.Charset JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.Calendar JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.Comparator JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.TimeZone JavaDoc;
36 import java.util.Map.Entry;
37
38 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
39 import javax.xml.parsers.ParserConfigurationException JavaDoc;
40
41 import org.eclipse.core.runtime.Assert;
42 import org.eclipse.core.runtime.CoreException;
43 import org.eclipse.core.runtime.IPath;
44 import org.eclipse.core.runtime.IProgressMonitor;
45 import org.eclipse.core.runtime.IStatus;
46 import org.eclipse.core.runtime.NullProgressMonitor;
47 import org.eclipse.core.runtime.OperationCanceledException;
48 import org.eclipse.core.runtime.Path;
49 import org.eclipse.core.runtime.Status;
50 import org.eclipse.core.runtime.SubProgressMonitor;
51
52 import org.eclipse.core.filesystem.EFS;
53 import org.eclipse.core.filesystem.IFileInfo;
54 import org.eclipse.core.filesystem.IFileStore;
55
56 import org.eclipse.ltk.core.refactoring.IRefactoringCoreStatusCodes;
57 import org.eclipse.ltk.core.refactoring.RefactoringContribution;
58 import org.eclipse.ltk.core.refactoring.RefactoringCore;
59 import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
60 import org.eclipse.ltk.core.refactoring.RefactoringDescriptorProxy;
61 import org.eclipse.ltk.core.refactoring.RefactoringSessionDescriptor;
62 import org.eclipse.ltk.core.refactoring.history.RefactoringHistory;
63
64 import org.eclipse.ltk.internal.core.refactoring.IRefactoringSerializationConstants;
65 import org.eclipse.ltk.internal.core.refactoring.RefactoringCoreMessages;
66 import org.eclipse.ltk.internal.core.refactoring.RefactoringCorePlugin;
67 import org.eclipse.ltk.internal.core.refactoring.RefactoringSessionReader;
68 import org.eclipse.ltk.internal.core.refactoring.RefactoringSessionTransformer;
69
70 import org.w3c.dom.Attr JavaDoc;
71 import org.w3c.dom.Document JavaDoc;
72 import org.w3c.dom.Element JavaDoc;
73 import org.w3c.dom.NamedNodeMap JavaDoc;
74 import org.w3c.dom.Node JavaDoc;
75 import org.w3c.dom.NodeList JavaDoc;
76 import org.w3c.dom.Text JavaDoc;
77 import org.xml.sax.InputSource JavaDoc;
78 import org.xml.sax.SAXException JavaDoc;
79
80 /**
81  * Manager for persistable refactoring histories.
82  *
83  * @since 3.2
84  */

85 public final class RefactoringHistoryManager {
86
87     /** The index component delimiter */
88     public static final char DELIMITER_COMPONENT= '\t';
89
90     /** The index entry delimiter */
91     public static final char DELIMITER_ENTRY= '\n';
92
93     /** The calendar instance */
94     private static final Calendar JavaDoc fgCalendar= Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00")); //$NON-NLS-1$
95

96     /**
97      * Checks whether the argument is well-formed.
98      *
99      * @param argument
100      * the argument
101      * @param whitespace
102      * <code>true</code> if the arguments should be checked for
103      * whitespace characters, <code>false</code> otherwise
104      * @throws CoreException
105      * if the argument violates any of the constraints
106      */

107     private static void checkArgument(final Object JavaDoc argument, final boolean whitespace) throws CoreException {
108         if (argument instanceof String JavaDoc) {
109             final String JavaDoc string= (String JavaDoc) argument;
110             final char[] characters= string.toCharArray();
111             if (characters.length == 0)
112                 throw new CoreException(new Status(IStatus.ERROR, RefactoringCore.ID_PLUGIN, IRefactoringCoreStatusCodes.REFACTORING_HISTORY_FORMAT_ERROR, RefactoringCoreMessages.RefactoringHistoryManager_empty_argument, null));
113             if (whitespace) {
114                 for (int index= 0; index < characters.length; index++) {
115                     if (Character.isWhitespace(characters[index]))
116                         throw new CoreException(new Status(IStatus.ERROR, RefactoringCore.ID_PLUGIN, IRefactoringCoreStatusCodes.REFACTORING_HISTORY_FORMAT_ERROR, RefactoringCoreMessages.RefactoringHistoryManager_whitespace_argument_key, null));
117                 }
118             }
119         } else
120             throw new CoreException(new Status(IStatus.ERROR, RefactoringCore.ID_PLUGIN, IRefactoringCoreStatusCodes.REFACTORING_HISTORY_FORMAT_ERROR, RefactoringCoreMessages.RefactoringHistoryManager_non_string_argument, null));
121     }
122
123     /**
124      * Checks whether the argument map is well-formed.
125      * <p>
126      * All arguments contained in the map are checked according to the rules of
127      * {@link RefactoringDescriptor}.
128      * </p>
129      *
130      * @param arguments
131      * the argument map
132      * @throws CoreException
133      * if the argument violates any of the constraints
134      */

135     public static void checkArgumentMap(final Map JavaDoc arguments) throws CoreException {
136         Assert.isNotNull(arguments);
137         for (final Iterator JavaDoc iterator= arguments.entrySet().iterator(); iterator.hasNext();) {
138             final Map.Entry JavaDoc entry= (Map.Entry JavaDoc) iterator.next();
139             checkArgument(entry.getKey(), true);
140             checkArgument(entry.getValue(), false);
141         }
142     }
143
144     /**
145      * Creates a new core exception representing an I/O error.
146      *
147      * @param exception
148      * the throwable to wrap
149      * @return the core exception
150      */

151     private static CoreException createCoreException(final Throwable JavaDoc exception) {
152         return new CoreException(new Status(IStatus.ERROR, RefactoringCore.ID_PLUGIN, IRefactoringCoreStatusCodes.REFACTORING_HISTORY_IO_ERROR, exception.getLocalizedMessage(), exception));
153     }
154
155     /**
156      * Escapes the specified string for the history index.
157      *
158      * @param string
159      * the string for the history index
160      * @return the escaped string
161      */

162     public static String JavaDoc escapeString(final String JavaDoc string) {
163         if (string.indexOf(DELIMITER_COMPONENT) < 0) {
164             final int length= string.length();
165             final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(length + 16);
166             for (int index= 0; index < length; index++) {
167                 final char character= string.charAt(index);
168                 if (DELIMITER_COMPONENT == character)
169                     buffer.append(DELIMITER_COMPONENT);
170                 buffer.append(character);
171             }
172             return buffer.toString();
173         }
174         return string;
175     }
176
177     /**
178      * Returns the argument map of the specified descriptor.
179      *
180      * @param descriptor
181      * the refactoring descriptor
182      * @return the argument map, or <code>null</code>
183      */

184     public static Map JavaDoc getArgumentMap(final RefactoringDescriptor descriptor) {
185         Map JavaDoc arguments= null;
186         final RefactoringContribution contribution= RefactoringContributionManager.getInstance().getRefactoringContribution(descriptor.getID());
187         if (contribution != null)
188             arguments= contribution.retrieveArgumentMap(descriptor);
189         else if (descriptor instanceof DefaultRefactoringDescriptor)
190             arguments= ((DefaultRefactoringDescriptor) descriptor).getArguments();
191         return arguments;
192     }
193
194     /**
195      * Reads refactoring descriptor proxies.
196      *
197      * @param store
198      * the file store to read
199      * @param project
200      * the name of the project, or <code>null</code> for the
201      * workspace
202      * @param collection
203      * the collection of proxies to fill in
204      * @param start
205      * the start time stamp, inclusive
206      * @param end
207      * the end time stamp, inclusive
208      * @param monitor
209      * the progress monitor to use
210      * @param task
211      * the task label to use
212      * @throws CoreException
213      * if an error occurs
214      */

215     private static void readRefactoringDescriptorProxies(final IFileStore store, final String JavaDoc project, final Collection JavaDoc collection, final long start, final long end, final IProgressMonitor monitor, final String JavaDoc task) throws CoreException {
216         try {
217             monitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_retrieving_history, 22);
218             final IFileInfo info= store.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 2, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
219             if (!info.isDirectory() && info.exists() && store.getName().equalsIgnoreCase(RefactoringHistoryService.NAME_INDEX_FILE)) {
220                 InputStream JavaDoc stream= null;
221                 try {
222                     stream= store.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
223                     final RefactoringDescriptorProxy[] proxies= readRefactoringDescriptorProxies(stream, project, start, end);
224                     for (int index= 0; index < proxies.length; index++)
225                         collection.add(proxies[index]);
226                     monitor.worked(1);
227                 } catch (IOException JavaDoc exception) {
228                     throw createCoreException(exception);
229                 } finally {
230                     monitor.worked(1);
231                     if (stream != null) {
232                         try {
233                             stream.close();
234                         } catch (IOException JavaDoc exception) {
235                             // Do nothing
236
}
237                     }
238                     monitor.worked(1);
239                 }
240             } else
241                 monitor.worked(4);
242             if (monitor.isCanceled())
243                 throw new OperationCanceledException();
244             final IFileStore[] stores= store.childStores(EFS.NONE, new SubProgressMonitor(monitor, 2, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
245             final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 12);
246             try {
247                 subMonitor.beginTask(task, stores.length);
248                 for (int index= 0; index < stores.length; index++)
249                     readRefactoringDescriptorProxies(stores[index], project, collection, start, end, new SubProgressMonitor(subMonitor, 1), task);
250             } finally {
251                 subMonitor.done();
252             }
253         } finally {
254             monitor.done();
255         }
256     }
257
258     /**
259      * Reads refactoring descriptor proxies from the specified input stream.
260      * <p>
261      * The refactoring descriptor proxies are returned in no particular order.
262      * </p>
263      *
264      * @param stream
265      * the input stream where to read from
266      * @param project
267      * the name of the project, or <code>null</code> for the
268      * workspace
269      * @param start
270      * the start time stamp, inclusive
271      * @param end
272      * the end time stamp, inclusive
273      * @return An array of refactoring descriptor proxies
274      * @throws IOException
275      * if an input/output error occurs
276      */

277     public static RefactoringDescriptorProxy[] readRefactoringDescriptorProxies(final InputStream JavaDoc stream, final String JavaDoc project, final long start, final long end) throws IOException JavaDoc {
278         final List JavaDoc list= new ArrayList JavaDoc();
279         final BufferedReader JavaDoc reader= new BufferedReader JavaDoc(new InputStreamReader JavaDoc(stream, IRefactoringSerializationConstants.OUTPUT_ENCODING));
280         while (reader.ready()) {
281             final String JavaDoc line= reader.readLine();
282             if (line != null) {
283                 final int index= line.indexOf(DELIMITER_COMPONENT);
284                 if (index > 0) {
285                     try {
286                         final long stamp= new Long JavaDoc(line.substring(0, index)).longValue();
287                         if (stamp >= start && stamp <= end)
288                             list.add(new DefaultRefactoringDescriptorProxy(unescapeString(line.substring(index + 1)), project, stamp));
289                     } catch (NumberFormatException JavaDoc exception) {
290                         // Just skip
291
}
292                 }
293             }
294         }
295         return (RefactoringDescriptorProxy[]) list.toArray(new RefactoringDescriptorProxy[list.size()]);
296     }
297
298     /**
299      * Reads refactoring descriptors from the specified input stream.
300      * <p>
301      * The refactoring descriptors are returned in no particular order.
302      * </p>
303      *
304      * @param stream
305      * the input stream where to read from
306      * @return An array of refactoring descriptor proxies
307      * @throws CoreException
308      * if an error occurs while reading the descriptors
309      */

310     public static RefactoringDescriptor[] readRefactoringDescriptors(final InputStream JavaDoc stream) throws CoreException {
311         final List JavaDoc list= new ArrayList JavaDoc(64);
312         readRefactoringDescriptors(stream, list, new NullProgressMonitor());
313         return (RefactoringDescriptor[]) list.toArray(new RefactoringDescriptor[list.size()]);
314     }
315
316     /**
317      * Reads refactoring descriptors from the specified input stream.
318      *
319      * @param stream
320      * the input stream where to read from
321      * @param collection
322      * the list of descriptors read from the history
323      * @param monitor
324      * the progress monitor to use
325      * @throws CoreException
326      * if an error occurs while reading the descriptors
327      */

328     private static void readRefactoringDescriptors(final InputStream JavaDoc stream, final Collection JavaDoc collection, final IProgressMonitor monitor) throws CoreException {
329         try {
330             monitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_retrieving_history, 1);
331             final RefactoringDescriptor[] results= new RefactoringSessionReader(true).readSession(new InputSource JavaDoc(new BufferedInputStream JavaDoc(stream))).getRefactorings();
332             for (int index= 0; index < results.length; index++)
333                 collection.add(results[index]);
334         } finally {
335             monitor.done();
336         }
337     }
338
339     /**
340      * Removes the refactoring history index tree spanned by the specified file
341      * store.
342      *
343      * @param store
344      * the file store spanning the history index tree
345      * @param monitor
346      * the progress monitor to use
347      * @param task
348      * the task label to use
349      * @throws CoreException
350      * if an error occurs while removing the index tree
351      */

352     private static void removeIndexTree(final IFileStore store, final IProgressMonitor monitor, final String JavaDoc task) throws CoreException {
353         try {
354             monitor.beginTask(task, 16);
355             final IFileInfo info= store.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
356             if (info.isDirectory()) {
357                 if (info.getName().equalsIgnoreCase(RefactoringHistoryService.NAME_HISTORY_FOLDER))
358                     return;
359                 final IFileStore[] stores= store.childStores(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
360                 final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL);
361                 try {
362                     subMonitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_updating_history, stores.length);
363                     for (int index= 0; index < stores.length; index++) {
364                         final IFileInfo current= stores[index].fetchInfo(EFS.NONE, new SubProgressMonitor(subMonitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
365                         if (current.isDirectory()) {
366                             final char[] characters= stores[index].getName().toCharArray();
367                             for (int offset= 0; offset < characters.length; offset++) {
368                                 if (Character.isDigit(characters[offset]))
369                                     return;
370                                 else
371                                     continue;
372                             }
373                         }
374                     }
375                 } finally {
376                     subMonitor.done();
377                 }
378             }
379             final IFileStore parent= store.getParent();
380             store.delete(0, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
381             removeIndexTree(parent, new SubProgressMonitor(monitor, 12, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), task);
382         } finally {
383             monitor.done();
384         }
385     }
386
387     /**
388      * Sorts the refactoring descriptor proxies in ascending order of their time
389      * stamps.
390      *
391      * @param descriptors
392      * the refactoring descriptors
393      */

394     public static void sortRefactoringDescriptorsAscending(final RefactoringDescriptor[] descriptors) {
395         Arrays.sort(descriptors, new Comparator JavaDoc() {
396
397             public final int compare(final Object JavaDoc first, final Object JavaDoc second) {
398                 final RefactoringDescriptor predecessor= (RefactoringDescriptor) first;
399                 final RefactoringDescriptor successor= (RefactoringDescriptor) second;
400                 final long delta= predecessor.getTimeStamp() - successor.getTimeStamp();
401                 if (delta > 0)
402                     return 1;
403                 else if (delta < 0)
404                     return -1;
405                 return 0;
406             }
407         });
408     }
409
410     /**
411      * Sorts the refactoring descriptor proxies in ascending order of their time
412      * stamps.
413      *
414      * @param proxies
415      * the refactoring descriptor proxies
416      */

417     public static void sortRefactoringDescriptorsAscending(final RefactoringDescriptorProxy[] proxies) {
418         Arrays.sort(proxies, new Comparator JavaDoc() {
419
420             public final int compare(final Object JavaDoc first, final Object JavaDoc second) {
421                 final RefactoringDescriptorProxy predecessor= (RefactoringDescriptorProxy) first;
422                 final RefactoringDescriptorProxy successor= (RefactoringDescriptorProxy) second;
423                 final long delta= predecessor.getTimeStamp() - successor.getTimeStamp();
424                 if (delta > 0)
425                     return 1;
426                 else if (delta < 0)
427                     return -1;
428                 return 0;
429             }
430         });
431     }
432
433     /**
434      * Sorts the refactoring descriptor proxies in descending order of their
435      * time stamps.
436      *
437      * @param proxies
438      * the refactoring descriptor proxies
439      */

440     public static void sortRefactoringDescriptorsDescending(final RefactoringDescriptorProxy[] proxies) {
441         Arrays.sort(proxies, new Comparator JavaDoc() {
442
443             public final int compare(final Object JavaDoc first, final Object JavaDoc second) {
444                 final RefactoringDescriptorProxy predecessor= (RefactoringDescriptorProxy) first;
445                 final RefactoringDescriptorProxy successor= (RefactoringDescriptorProxy) second;
446                 final long delta= successor.getTimeStamp() - predecessor.getTimeStamp();
447                 if (delta > 0)
448                     return 1;
449                 else if (delta < 0)
450                     return -1;
451                 return 0;
452             }
453         });
454     }
455
456     /**
457      * Returns a path representing the history part for the specified time
458      * stamp.
459      *
460      * @param stamp
461      * the time stamp
462      * @return A path representing the folder of the history part
463      */

464     public static IPath stampToPath(final long stamp) {
465         fgCalendar.setTimeInMillis(stamp);
466         final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(256);
467         buffer.append(fgCalendar.get(Calendar.YEAR));
468         buffer.append(IPath.SEPARATOR);
469         buffer.append(fgCalendar.get(Calendar.MONTH) + 1);
470         buffer.append(IPath.SEPARATOR);
471         buffer.append(fgCalendar.get(Calendar.WEEK_OF_YEAR));
472         return new Path(buffer.toString());
473     }
474
475     /**
476      * Transforms the specified refactoring descriptor into a DOM node.
477      *
478      * @param descriptor
479      * the descriptor to transform
480      * @param projects
481      * <code>true</code> to include project information,
482      * <code>false</code> otherwise
483      * @return the DOM node representing the refactoring descriptor
484      * @throws CoreException
485      * if an error occurs while transforming the descriptor
486      */

487     private static Document JavaDoc transformDescriptor(final RefactoringDescriptor descriptor, final boolean projects) throws CoreException {
488         final RefactoringSessionTransformer transformer= new RefactoringSessionTransformer(projects);
489         try {
490             transformer.beginSession(null, IRefactoringSerializationConstants.CURRENT_VERSION);
491             try {
492                 final String JavaDoc id= descriptor.getID();
493                 transformer.beginRefactoring(id, descriptor.getTimeStamp(), descriptor.getProject(), descriptor.getDescription(), descriptor.getComment(), descriptor.getFlags());
494                 final Map JavaDoc arguments= getArgumentMap(descriptor);
495                 if (arguments != null) {
496                     checkArgumentMap(arguments);
497                     for (final Iterator JavaDoc iterator= arguments.entrySet().iterator(); iterator.hasNext();) {
498                         final Map.Entry JavaDoc entry= (Entry) iterator.next();
499                         transformer.createArgument((String JavaDoc) entry.getKey(), (String JavaDoc) entry.getValue());
500                     }
501                 }
502             } finally {
503                 transformer.endRefactoring();
504             }
505         } finally {
506             transformer.endSession();
507         }
508         return transformer.getResult();
509     }
510
511     /**
512      * Un-escapes the specified string from the history index.
513      *
514      * @param string
515      * the string from the history index
516      * @return the un-escaped string
517      */

518     public static String JavaDoc unescapeString(final String JavaDoc string) {
519         if (string.indexOf(DELIMITER_COMPONENT) < 0) {
520             final int length= string.length();
521             final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(length);
522             for (int index= 0; index < length; index++) {
523                 final char character= string.charAt(index);
524                 if (DELIMITER_COMPONENT == character) {
525                     if (index < length - 1) {
526                         final char escape= string.charAt(index + 1);
527                         if (DELIMITER_COMPONENT == escape)
528                             continue;
529                     }
530                 }
531                 buffer.append(character);
532             }
533             return buffer.toString();
534         }
535         return string;
536     }
537
538     /**
539      * Writes the specified index entry to the refactoring history.
540      *
541      * @param file
542      * the history index file
543      * @param proxies
544      * the refactoring descriptors
545      * @param flags
546      * the flags to use (either {@link EFS#NONE} or
547      * {@link EFS#APPEND})
548      * @param monitor
549      * the progress monitor to use
550      * @param task
551      * the task label
552      * @throws CoreException
553      * if an error occurs while writing the index entry
554      * @throws IOException
555      * if an input/output error occurs
556      */

557     private static void writeIndexEntry(final IFileStore file, final RefactoringDescriptorProxy[] proxies, final int flags, final IProgressMonitor monitor, final String JavaDoc task) throws CoreException, IOException JavaDoc {
558         OutputStream JavaDoc output= null;
559         try {
560             monitor.beginTask(task, 2);
561             file.getParent().mkdir(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
562             output= new BufferedOutputStream JavaDoc(file.openOutputStream(flags, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
563             writeRefactoringDescriptorProxies(output, proxies);
564         } finally {
565             monitor.done();
566             if (output != null) {
567                 try {
568                     output.close();
569                 } catch (IOException JavaDoc exception) {
570                     // Do nothing
571
}
572             }
573         }
574     }
575
576     /**
577      * Writes refactoring descriptor proxies to the specified output stream.
578      *
579      * @param stream
580      * the output stream where to write to
581      * @param proxies
582      * the refactoring descriptor proxies to write
583      * @throws IOException
584      * if an input/output error occurs
585      */

586     public static void writeRefactoringDescriptorProxies(final OutputStream JavaDoc stream, final RefactoringDescriptorProxy[] proxies) throws IOException JavaDoc {
587         final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(proxies.length * 64);
588         sortRefactoringDescriptorsAscending(proxies);
589         for (int index= 0; index < proxies.length; index++) {
590             buffer.append(proxies[index].getTimeStamp());
591             buffer.append(DELIMITER_COMPONENT);
592             buffer.append(escapeString(proxies[index].getDescription()));
593             buffer.append(DELIMITER_ENTRY);
594         }
595         stream.write(buffer.toString().getBytes(IRefactoringSerializationConstants.OUTPUT_ENCODING));
596     }
597
598     /**
599      * A simple XML writer. Using this instead of the javax.xml.transform classes allows
600      * compilation against JCL Foundation (bug 80053).
601      */

602     private static final class DOMWriter extends PrintWriter JavaDoc {
603
604         private int tab;
605
606         /* constants */
607         private static final String JavaDoc XML_VERSION= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
608

609         /**
610          * Creates a new DOM writer on the given output writer.
611          *
612          * @param output the output writer
613          */

614         public DOMWriter(Writer JavaDoc output) {
615             super(output);
616             tab= 0;
617         }
618
619         public void printDocument(Document JavaDoc doc) {
620             println(XML_VERSION);
621             printElement(doc.getDocumentElement());
622         }
623
624         /**
625          * Prints the given element.
626          *
627          * @param element the element to print
628          */

629         public void printElement(Element JavaDoc element) {
630             // Ensure extra whitespace is not emitted next to a Text node,
631
// as that will result in a situation where the restored text data is not the
632
// same as the saved text data.
633
boolean hasChildren= element.hasChildNodes();
634             startTag(element, hasChildren);
635             if (hasChildren) {
636                 tab++;
637                 boolean prevWasText= false;
638                 NodeList JavaDoc children= element.getChildNodes();
639                 for (int i= 0; i < children.getLength(); i++) {
640                     Node JavaDoc node= children.item(i);
641                     if (node instanceof Element JavaDoc) {
642                         if (!prevWasText) {
643                             println();
644                             printTabulation();
645                         }
646                         printElement((Element JavaDoc) children.item(i));
647                         prevWasText= false;
648                     } else if (node instanceof Text JavaDoc) {
649                         print(getEscaped(node.getNodeValue()));
650                         prevWasText= true;
651                     }
652                 }
653                 tab--;
654                 if (!prevWasText) {
655                     println();
656                     printTabulation();
657                 }
658                 endTag(element);
659             }
660         }
661
662         private void printTabulation() {
663             // Indenting is disabled, as it can affect the result of getTextData().
664
// In 3.0, elements were separated by a newline but not indented.
665
// This causes getTextData() to return "\n" even if no text data had explicitly been set.
666
// The code here emulates that behaviour.
667

668 // for (int i = 0; i < tab; i++)
669
// super.print("\t"); //$NON-NLS-1$
670
}
671
672         private void startTag(Element JavaDoc element, boolean hasChildren) {
673             StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
674             sb.append("<"); //$NON-NLS-1$
675
sb.append(element.getTagName());
676             NamedNodeMap JavaDoc attributes= element.getAttributes();
677             for (int i= 0; i < attributes.getLength(); i++) {
678                 Attr JavaDoc attribute= (Attr JavaDoc) attributes.item(i);
679                 sb.append(" "); //$NON-NLS-1$
680
sb.append(attribute.getName());
681                 sb.append("=\""); //$NON-NLS-1$
682
sb.append(getEscaped(String.valueOf(attribute.getValue())));
683                 sb.append("\""); //$NON-NLS-1$
684
}
685             sb.append(hasChildren ? ">" : "/>"); //$NON-NLS-1$ //$NON-NLS-2$
686
print(sb.toString());
687         }
688
689         private void endTag(Element JavaDoc element) {
690             StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
691             sb.append("</"); //$NON-NLS-1$
692
sb.append(element.getNodeName());
693             sb.append(">"); //$NON-NLS-1$
694
print(sb.toString());
695         }
696
697         private static void appendEscapedChar(StringBuffer JavaDoc buffer, char c) {
698             String JavaDoc replacement= getReplacement(c);
699             if (replacement != null) {
700                 buffer.append('&');
701                 buffer.append(replacement);
702                 buffer.append(';');
703             } else {
704                 buffer.append(c);
705             }
706         }
707
708         private static String JavaDoc getEscaped(String JavaDoc s) {
709             StringBuffer JavaDoc result= new StringBuffer JavaDoc(s.length() + 10);
710             for (int i= 0; i < s.length(); ++i) {
711                 appendEscapedChar(result, s.charAt(i));
712             }
713             return result.toString();
714         }
715
716         private static String JavaDoc getReplacement(char c) {
717             // Encode special XML characters into the equivalent character references.
718
// The first five are defined by default for all XML documents.
719
// The next three (#xD, #xA, #x9) are encoded to avoid them
720
// being converted to spaces on deserialization
721
// (fixes bug 93720)
722
switch (c) {
723                 case '<':
724                     return "lt"; //$NON-NLS-1$
725
case '>':
726                     return "gt"; //$NON-NLS-1$
727
case '"':
728                     return "quot"; //$NON-NLS-1$
729
case '\'':
730                     return "apos"; //$NON-NLS-1$
731
case '&':
732                     return "amp"; //$NON-NLS-1$
733
case '\r':
734                     return "#x0D"; //$NON-NLS-1$
735
case '\n':
736                     return "#x0A"; //$NON-NLS-1$
737
case '\u0009':
738                     return "#x09"; //$NON-NLS-1$
739
}
740             return null;
741         }
742     }
743
744     /**
745      * Writes refactoring session descriptor to the specified output stream.
746      *
747      * @param stream
748      * the output stream where to write to
749      * @param descriptor
750      * the refactoring session descriptors to write
751      * @param stamps
752      * <code>true</code> to write time stamps as well,
753      * <code>false</code> otherwise
754      * @throws CoreException
755      * if an error occurs while writing the refactoring session
756      * descriptor
757      */

758     public static void writeRefactoringSession(final OutputStream JavaDoc stream, final RefactoringSessionDescriptor descriptor, final boolean stamps) throws CoreException {
759         final RefactoringSessionTransformer transformer= new RefactoringSessionTransformer(true);
760         final RefactoringDescriptor[] descriptors= descriptor.getRefactorings();
761         try {
762             transformer.beginSession(descriptor.getComment(), descriptor.getVersion());
763             for (int index= 0; index < descriptors.length; index++) {
764                 final RefactoringDescriptor current= descriptors[index];
765                 if (current != null) {
766                     try {
767                         long stamp= stamps ? current.getTimeStamp() : -1;
768                         transformer.beginRefactoring(current.getID(), stamp, current.getProject(), current.getDescription(), current.getComment(), current.getFlags());
769                         final Map JavaDoc arguments= getArgumentMap(current);
770                         if (arguments != null) {
771                             checkArgumentMap(arguments);
772                             for (final Iterator JavaDoc iterator= arguments.entrySet().iterator(); iterator.hasNext();) {
773                                 final Map.Entry JavaDoc entry= (Entry) iterator.next();
774                                 transformer.createArgument((String JavaDoc) entry.getKey(), (String JavaDoc) entry.getValue());
775                             }
776                         }
777                     } finally {
778                         transformer.endRefactoring();
779                     }
780                 }
781             }
782         } finally {
783             transformer.endSession();
784         }
785         final Document JavaDoc result= transformer.getResult();
786         writeNode(stream, result);
787     }
788
789     private static void writeNode(final OutputStream JavaDoc stream, Document JavaDoc document) {
790         OutputStreamWriter JavaDoc outputStreamWriter= new OutputStreamWriter JavaDoc(stream, Charset.forName("UTF-8")); //$NON-NLS-1$
791
DOMWriter writer= new DOMWriter(outputStreamWriter);
792         writer.printDocument(document);
793         writer.flush();
794     }
795
796     /** The cached session descriptor, or <code>null</code> */
797     private RefactoringSessionDescriptor fCachedDescriptor= null;
798
799     /** The cached document, or <code>null</code> */
800     private Document JavaDoc fCachedDocument= null;
801
802     /** The cached path, or <code>null</code> */
803     private IPath fCachedPath= null;
804
805     /** The cached file store, or <code>null</code> */
806     private IFileStore fCachedStore= null;
807
808     /** The history file store */
809     private final IFileStore fHistoryStore;
810
811     /**
812      * The non-empty name of the managed project, or <code>null</code> for the
813      * workspace
814      */

815     private final String JavaDoc fProjectName;
816
817     /**
818      * Creates a new refactoring history manager.
819      *
820      * @param store
821      * the history file store
822      * @param name
823      * the non-empty name of the managed project, or
824      * <code>null</code> for the workspace
825      */

826     RefactoringHistoryManager(final IFileStore store, final String JavaDoc name) {
827         Assert.isNotNull(store);
828         Assert.isTrue(name == null || !"".equals(name)); //$NON-NLS-1$
829
fHistoryStore= store;
830         fProjectName= name;
831     }
832
833     /**
834      * Adds the specified refactoring descriptor to the refactoring history.
835      *
836      * @param descriptor
837      * the refactoring descriptor to add
838      * @param sort
839      * <code>true</code> if the refactoring descriptor should be
840      * inserted into the history according to its time stamp,
841      * <code>false</code> if the descriptor is assumed to be the
842      * most recent one, and its simply appended
843      * @param monitor
844      * the progress monitor to use
845      * @throws CoreException
846      * if an error occurs while adding the descriptor to the history
847      */

848     void addRefactoringDescriptor(final RefactoringDescriptor descriptor, final boolean sort, final IProgressMonitor monitor) throws CoreException {
849         try {
850             monitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_updating_history, 18);
851             final long stamp= descriptor.getTimeStamp();
852             if (stamp >= 0) {
853                 final IPath path= stampToPath(stamp);
854                 final IFileStore folder= fHistoryStore.getChild(path);
855                 final IFileStore history= folder.getChild(RefactoringHistoryService.NAME_HISTORY_FILE);
856                 final IFileStore index= folder.getChild(RefactoringHistoryService.NAME_INDEX_FILE);
857                 final RefactoringDescriptorProxy[] proxies= new RefactoringDescriptorProxy[] { new DefaultRefactoringDescriptorProxy(descriptor.getDescription(), descriptor.getProject(), descriptor.getTimeStamp())};
858                 if (history.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) {
859                     InputStream JavaDoc input= null;
860                     try {
861                         input= new BufferedInputStream JavaDoc(history.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
862                         final Document JavaDoc document= getCachedDocument(path, input);
863                         try {
864                             input.close();
865                             input= null;
866                         } catch (IOException JavaDoc exception) {
867                             // Do nothing
868
}
869                         monitor.worked(1);
870                         final Document JavaDoc result= transformDescriptor(descriptor, false);
871                         if (result != null) {
872                             boolean found= false;
873                             final NodeList JavaDoc list= result.getElementsByTagName(IRefactoringSerializationConstants.ELEMENT_REFACTORING);
874                             final Element JavaDoc root= document.getDocumentElement();
875                             if (sort) {
876                                 final String JavaDoc string= Long.toString(stamp);
877                                 for (int offset= 0; offset < list.getLength(); offset++) {
878                                     final Element JavaDoc element= (Element JavaDoc) list.item(offset);
879                                     final String JavaDoc attribute= element.getAttribute(IRefactoringSerializationConstants.ATTRIBUTE_STAMP);
880                                     if (attribute != null) {
881                                         if (string.compareTo(attribute) > 0) {
882                                             root.insertBefore(document.importNode(element, true), element);
883                                             found= true;
884                                             break;
885                                         }
886                                     }
887                                 }
888                             }
889                             if (!found)
890                                 root.appendChild(document.importNode(list.item(0), true));
891                             writeHistoryEntry(history, document, new SubProgressMonitor(monitor, 10, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
892                             if (sort) {
893                                 final Set JavaDoc set= new HashSet JavaDoc(64);
894                                 readRefactoringDescriptorProxies(index, null, set, 0, Long.MAX_VALUE, new SubProgressMonitor(monitor, 2), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
895                                 writeIndexEntry(index, (RefactoringDescriptorProxy[]) set.toArray(new RefactoringDescriptorProxy[set.size()]), EFS.NONE, new SubProgressMonitor(monitor, 3, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
896                             } else
897                                 writeIndexEntry(index, proxies, EFS.APPEND, new SubProgressMonitor(monitor, 5, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
898                         }
899                     } catch (ParserConfigurationException JavaDoc exception) {
900                         throw createCoreException(exception);
901                     } catch (IOException JavaDoc exception) {
902                         throw createCoreException(exception);
903                     } catch (SAXException JavaDoc exception) {
904                         throw createCoreException(exception);
905                     } finally {
906                         if (input != null) {
907                             try {
908                                 input.close();
909                             } catch (IOException JavaDoc exception) {
910                                 // Do nothing
911
}
912                         }
913                     }
914                 } else {
915                     try {
916                         final Document JavaDoc result= transformDescriptor(descriptor, false);
917                         writeHistoryEntry(history, result, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
918                         writeIndexEntry(index, proxies, EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
919                     } catch (IOException JavaDoc exception) {
920                         throw createCoreException(exception);
921                     }
922                 }
923             }
924         } finally {
925             monitor.done();
926         }
927     }
928
929     /**
930      * Returns the cached refactoring history document.
931      *
932      * @param path
933      * the path of the document
934      * @param input
935      * the input stream where to read the document
936      * @return the cached refactoring history document
937      * @throws SAXException
938      * if an error occurs while parsing the history entry
939      * @throws IOException
940      * if an input/output error occurs
941      * @throws ParserConfigurationException
942      * if an error occurs in the parser configuration
943      */

944     private Document JavaDoc getCachedDocument(final IPath path, final InputStream JavaDoc input) throws SAXException JavaDoc, IOException JavaDoc, ParserConfigurationException JavaDoc {
945         if (path.equals(fCachedPath) && fCachedDocument != null)
946             return fCachedDocument;
947         final Document JavaDoc document= DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource JavaDoc(input));
948         fCachedDocument= document;
949         fCachedPath= path;
950         return document;
951     }
952
953     /**
954      * Returns the cached refactoring session descriptor.
955      *
956      * @param store
957      * the file store of the descriptor
958      * @param input
959      * the input stream where to read the descriptor
960      * @return the cached refactoring session descriptor
961      * @throws CoreException
962      * if an error occurs while reading the session
963      */

964     private RefactoringSessionDescriptor getCachedSession(final IFileStore store, final InputStream JavaDoc input) throws CoreException {
965         if (store.equals(fCachedStore) && fCachedDescriptor != null)
966             return fCachedDescriptor;
967         final RefactoringSessionDescriptor descriptor= new RefactoringSessionReader(true).readSession(new InputSource JavaDoc(input));
968         fCachedDescriptor= descriptor;
969         fCachedStore= store;
970         return descriptor;
971     }
972
973     /**
974      * Reads the refactoring history from disk.
975      *
976      * @param start
977      * the start time stamp, inclusive
978      * @param end
979      * the end time stamp, inclusive
980      * @param monitor
981      * the progress monitor to use
982      * @return the refactoring history
983      */

984     RefactoringHistory readRefactoringHistory(final long start, final long end, final IProgressMonitor monitor) {
985         try {
986             monitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_retrieving_history, 200);
987             final Set JavaDoc set= new HashSet JavaDoc();
988             try {
989                 if (fHistoryStore.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 20, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists())
990                     readRefactoringDescriptorProxies(fHistoryStore, fProjectName, set, start, end, new SubProgressMonitor(monitor, 80), RefactoringCoreMessages.RefactoringHistoryService_retrieving_history);
991                 final IFileStore store= EFS.getLocalFileSystem().getStore(RefactoringCorePlugin.getDefault().getStateLocation()).getChild(RefactoringHistoryService.NAME_HISTORY_FOLDER).getChild(RefactoringHistoryService.NAME_WORKSPACE_PROJECT);
992                 if (store.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 20, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists())
993                     readRefactoringDescriptorProxies(store, null, set, start, end, new SubProgressMonitor(monitor, 80), RefactoringCoreMessages.RefactoringHistoryService_retrieving_history);
994             } catch (CoreException exception) {
995                 RefactoringCorePlugin.log(exception);
996             }
997             final RefactoringDescriptorProxy[] proxies= new RefactoringDescriptorProxy[set.size()];
998             set.toArray(proxies);
999             return new RefactoringHistoryImplementation(proxies);
1000        } finally {
1001            monitor.done();
1002        }
1003    }
1004
1005    /**
1006     * Removes refactoring descriptors from the managed history.
1007     * <p>
1008     * All refactoring descriptors must be from the history entry denoted by the
1009     * specified path.
1010     * </p>
1011     *
1012     * @param proxies
1013     * the refactoring descriptors
1014     * @param path
1015     * the path of the history entry
1016     * @param monitor
1017     * the progress monitor to use
1018     * @param task
1019     * the task label to use
1020     * @throws CoreException
1021     * if an error occurs
1022     */

1023    private void removeRefactoringDescriptors(final RefactoringDescriptorProxy[] proxies, final IPath path, final IProgressMonitor monitor, final String JavaDoc task) throws CoreException {
1024        try {
1025            monitor.beginTask(task, 5);
1026            final IFileStore folder= fHistoryStore.getChild(path);
1027            final IFileStore index= folder.getChild(RefactoringHistoryService.NAME_INDEX_FILE);
1028            if (index.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) {
1029                final Set JavaDoc resultingProxies= new HashSet JavaDoc(64);
1030                readRefactoringDescriptorProxies(index, null, resultingProxies, 0, Long.MAX_VALUE, new SubProgressMonitor(monitor, 1), task);
1031                if (resultingProxies.size() == proxies.length)
1032                    removeIndexTree(folder, new SubProgressMonitor(monitor, 1), task);
1033                else {
1034                    final IFileStore history= folder.getChild(RefactoringHistoryService.NAME_HISTORY_FILE);
1035                    if (history.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) {
1036                        InputStream JavaDoc input= null;
1037                        Document JavaDoc document= null;
1038                        try {
1039                            input= new BufferedInputStream JavaDoc(history.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
1040                            document= getCachedDocument(path, input);
1041                        } catch (ParserConfigurationException JavaDoc exception) {
1042                            throw createCoreException(exception);
1043                        } catch (IOException JavaDoc exception) {
1044                            throw createCoreException(exception);
1045                        } catch (SAXException JavaDoc exception) {
1046                            throw createCoreException(exception);
1047                        } finally {
1048                            if (input != null) {
1049                                try {
1050                                    input.close();
1051                                } catch (IOException JavaDoc exception) {
1052                                    // Do nothing
1053
}
1054                            }
1055                        }
1056                        final Set JavaDoc removedNodes= new HashSet JavaDoc(proxies.length);
1057                        final NodeList JavaDoc list= document.getElementsByTagName(IRefactoringSerializationConstants.ELEMENT_REFACTORING);
1058                        final int length= list.getLength();
1059                        for (int offset= 0; offset < length; offset++) {
1060                            final Node JavaDoc node= list.item(offset);
1061                            final NamedNodeMap JavaDoc attributes= node.getAttributes();
1062                            if (attributes != null) {
1063                                final Node JavaDoc item= attributes.getNamedItem(IRefactoringSerializationConstants.ATTRIBUTE_STAMP);
1064                                if (item != null) {
1065                                    final String JavaDoc value= item.getNodeValue();
1066                                    if (value != null) {
1067                                        for (int current= 0; current < proxies.length; current++) {
1068                                            final RefactoringDescriptorProxy proxy= proxies[current];
1069                                            final long stamp= proxy.getTimeStamp();
1070                                            if (value.equals(String.valueOf(stamp))) {
1071                                                resultingProxies.remove(new DefaultRefactoringDescriptorProxy(proxy.getDescription(), proxy.getProject(), stamp));
1072                                                removedNodes.add(node);
1073                                            }
1074                                        }
1075                                    }
1076                                }
1077                            }
1078                        }
1079                        for (final Iterator JavaDoc iterator= removedNodes.iterator(); iterator.hasNext();) {
1080                            final Node JavaDoc node= (Node JavaDoc) iterator.next();
1081                            node.getParentNode().removeChild(node);
1082                        }
1083                        try {
1084                            writeIndexEntry(index, (RefactoringDescriptorProxy[]) resultingProxies.toArray(new RefactoringDescriptorProxy[resultingProxies.size()]), EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), task);
1085                            writeHistoryEntry(history, document, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), task);
1086                        } catch (IOException JavaDoc exception) {
1087                            throw createCoreException(exception);
1088                        }
1089                    }
1090                }
1091            }
1092        } finally {
1093            monitor.done();
1094        }
1095    }
1096
1097    /**
1098     * Removes refactoring descriptors from the managed history.
1099     *
1100     * @param proxies
1101     * the refactoring descriptors
1102     * @param monitor
1103     * the progress monitor to use
1104     * @param task
1105     * the task label to use
1106     * @throws CoreException
1107     * if an error occurs
1108     */

1109    void removeRefactoringDescriptors(final RefactoringDescriptorProxy[] proxies, final IProgressMonitor monitor, final String JavaDoc task) throws CoreException {
1110        try {
1111            final Map JavaDoc paths= new HashMap JavaDoc();
1112            monitor.beginTask(task, proxies.length + 300);
1113            for (int index= 0; index < proxies.length; index++) {
1114                final IPath path= stampToPath(proxies[index].getTimeStamp());
1115                Collection JavaDoc collection= (Collection JavaDoc) paths.get(path);
1116                if (collection == null) {
1117                    collection= new ArrayList JavaDoc(64);
1118                    paths.put(path, collection);
1119                }
1120                collection.add(proxies[index]);
1121            }
1122            final IProgressMonitor subMonitor= new SubProgressMonitor(monitor, 300);
1123            try {
1124                final Set JavaDoc entries= paths.entrySet();
1125                subMonitor.beginTask(task, entries.size());
1126                for (final Iterator JavaDoc iterator= entries.iterator(); iterator.hasNext();) {
1127                    final Map.Entry JavaDoc entry= (Map.Entry JavaDoc) iterator.next();
1128                    final Collection JavaDoc collection= (Collection JavaDoc) entry.getValue();
1129                    removeRefactoringDescriptors((RefactoringDescriptorProxy[]) collection.toArray(new RefactoringDescriptorProxy[collection.size()]), (IPath) entry.getKey(), new SubProgressMonitor(subMonitor, 1), task);
1130                }
1131            } finally {
1132                subMonitor.done();
1133            }
1134        } finally {
1135            monitor.done();
1136        }
1137    }
1138
1139    /**
1140     * Requests the resolved refactoring descriptor associated with the given
1141     * proxy.
1142     *
1143     * @param proxy
1144     * the refactoring descriptor proxy
1145     * @param monitor
1146     * the progress monitor to use
1147     * @return the associated refactoring descriptor, or <code>null</code>
1148     */

1149    RefactoringDescriptor requestDescriptor(final RefactoringDescriptorProxy proxy, final IProgressMonitor monitor) {
1150        try {
1151            monitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_resolving_information, 2);
1152            final long stamp= proxy.getTimeStamp();
1153            if (stamp >= 0) {
1154                InputStream JavaDoc input= null;
1155                try {
1156                    final IFileStore folder= fHistoryStore.getChild(stampToPath(stamp));
1157                    final IFileStore file= folder.getChild(RefactoringHistoryService.NAME_HISTORY_FILE);
1158                    if (file.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) {
1159                        input= new BufferedInputStream JavaDoc(file.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
1160                        final RefactoringSessionDescriptor descriptor= getCachedSession(file, input);
1161                        if (descriptor != null) {
1162                            final RefactoringDescriptor[] descriptors= descriptor.getRefactorings();
1163                            for (int index= 0; index < descriptors.length; index++) {
1164                                if (descriptors[index].getTimeStamp() == stamp) {
1165                                    final RefactoringDescriptor result= descriptors[index];
1166                                    result.setProject(fProjectName);
1167                                    return result;
1168                                }
1169                            }
1170                        }
1171                    }
1172                } catch (CoreException exception) {
1173                    // Do nothing
1174
} finally {
1175                    try {
1176                        if (input != null)
1177                            input.close();
1178                    } catch (IOException JavaDoc exception) {
1179                        // Do nothing
1180
}
1181                }
1182            }
1183        } finally {
1184            monitor.done();
1185        }
1186        return null;
1187    }
1188
1189    /**
1190     * Sets the comment of the specified refactoring.
1191     *
1192     * @param proxy
1193     * the refactoring descriptor proxy
1194     * @param comment
1195     * the comment
1196     * @param monitor
1197     * the progress monitor to use
1198     * @throws CoreException
1199     * if an error occurs while setting the comment
1200     */

1201    void setComment(final RefactoringDescriptorProxy proxy, final String JavaDoc comment, final IProgressMonitor monitor) throws CoreException {
1202        try {
1203            monitor.beginTask(RefactoringCoreMessages.RefactoringHistoryService_updating_history, 100);
1204            final long stamp= proxy.getTimeStamp();
1205            if (stamp >= 0) {
1206                final IPath path= stampToPath(stamp);
1207                final IFileStore folder= fHistoryStore.getChild(path);
1208                final IFileStore history= folder.getChild(RefactoringHistoryService.NAME_HISTORY_FILE);
1209                if (history.fetchInfo(EFS.NONE, new SubProgressMonitor(monitor, 20, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)).exists()) {
1210                    InputStream JavaDoc input= null;
1211                    try {
1212                        input= new BufferedInputStream JavaDoc(history.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 40, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
1213                        final Document JavaDoc document= getCachedDocument(path, input);
1214                        try {
1215                            input.close();
1216                            input= null;
1217                        } catch (IOException JavaDoc exception) {
1218                            // Do nothing
1219
}
1220                        final String JavaDoc time= String.valueOf(stamp);
1221                        final NodeList JavaDoc list= document.getElementsByTagName(IRefactoringSerializationConstants.ELEMENT_REFACTORING);
1222                        for (int index= 0; index < list.getLength(); index++) {
1223                            final Element JavaDoc element= (Element JavaDoc) list.item(index);
1224                            if (time.equals(element.getAttribute(IRefactoringSerializationConstants.ATTRIBUTE_STAMP))) {
1225                                element.setAttribute(IRefactoringSerializationConstants.ATTRIBUTE_COMMENT, comment);
1226                                break;
1227                            }
1228                        }
1229                        writeHistoryEntry(history, document, new SubProgressMonitor(monitor, 40, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL), RefactoringCoreMessages.RefactoringHistoryService_updating_history);
1230                    } catch (ParserConfigurationException JavaDoc exception) {
1231                        throw createCoreException(exception);
1232                    } catch (IOException JavaDoc exception) {
1233                        throw createCoreException(exception);
1234                    } catch (SAXException JavaDoc exception) {
1235                        throw createCoreException(exception);
1236                    } finally {
1237                        if (input != null) {
1238                            try {
1239                                input.close();
1240                            } catch (IOException JavaDoc exception) {
1241                                // Do nothing
1242
}
1243                        }
1244                    }
1245                }
1246            }
1247        } finally {
1248            monitor.done();
1249        }
1250    }
1251
1252    /**
1253     * Writes the specified document node into the refactoring history.
1254     *
1255     * @param file
1256     * the refactoring history file
1257     * @param document
1258     * the document representing the history entry
1259     * @param monitor
1260     * the progress monitor to use
1261     * @param task
1262     * the task label
1263     * @throws CoreException
1264     * if an error occurs while adding the history entry
1265     */

1266    private void writeHistoryEntry(final IFileStore file, final Document JavaDoc document, final IProgressMonitor monitor, final String JavaDoc task) throws CoreException {
1267        OutputStream JavaDoc output= null;
1268        try {
1269            monitor.beginTask(task, 2);
1270            file.getParent().mkdir(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
1271            output= new BufferedOutputStream JavaDoc(file.openOutputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL)));
1272            writeNode(output, document);
1273        } finally {
1274            fCachedDocument= null;
1275            fCachedPath= null;
1276            fCachedDescriptor= null;
1277            fCachedStore= null;
1278            if (output != null) {
1279                try {
1280                    output.close();
1281                } catch (IOException JavaDoc exception) {
1282                    // Do nothing
1283
}
1284            }
1285            monitor.done();
1286        }
1287    }
1288}
1289
Popular Tags