1 11 package org.eclipse.ltk.internal.core.refactoring.history; 12 13 import java.io.BufferedInputStream ; 14 import java.io.BufferedOutputStream ; 15 import java.io.BufferedReader ; 16 import java.io.IOException ; 17 import java.io.InputStream ; 18 import java.io.InputStreamReader ; 19 import java.io.OutputStream ; 20 import java.io.OutputStreamWriter ; 21 import java.io.PrintWriter ; 22 import java.io.Writer ; 23 import java.nio.charset.Charset ; 24 import java.util.ArrayList ; 25 import java.util.Arrays ; 26 import java.util.Calendar ; 27 import java.util.Collection ; 28 import java.util.Comparator ; 29 import java.util.HashMap ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 import java.util.TimeZone ; 36 import java.util.Map.Entry; 37 38 import javax.xml.parsers.DocumentBuilderFactory ; 39 import javax.xml.parsers.ParserConfigurationException ; 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 ; 71 import org.w3c.dom.Document ; 72 import org.w3c.dom.Element ; 73 import org.w3c.dom.NamedNodeMap ; 74 import org.w3c.dom.Node ; 75 import org.w3c.dom.NodeList ; 76 import org.w3c.dom.Text ; 77 import org.xml.sax.InputSource ; 78 import org.xml.sax.SAXException ; 79 80 85 public final class RefactoringHistoryManager { 86 87 88 public static final char DELIMITER_COMPONENT= '\t'; 89 90 91 public static final char DELIMITER_ENTRY= '\n'; 92 93 94 private static final Calendar fgCalendar= Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00")); 96 107 private static void checkArgument(final Object argument, final boolean whitespace) throws CoreException { 108 if (argument instanceof String ) { 109 final String string= (String ) 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 135 public static void checkArgumentMap(final Map arguments) throws CoreException { 136 Assert.isNotNull(arguments); 137 for (final Iterator iterator= arguments.entrySet().iterator(); iterator.hasNext();) { 138 final Map.Entry entry= (Map.Entry ) iterator.next(); 139 checkArgument(entry.getKey(), true); 140 checkArgument(entry.getValue(), false); 141 } 142 } 143 144 151 private static CoreException createCoreException(final Throwable exception) { 152 return new CoreException(new Status(IStatus.ERROR, RefactoringCore.ID_PLUGIN, IRefactoringCoreStatusCodes.REFACTORING_HISTORY_IO_ERROR, exception.getLocalizedMessage(), exception)); 153 } 154 155 162 public static String escapeString(final String string) { 163 if (string.indexOf(DELIMITER_COMPONENT) < 0) { 164 final int length= string.length(); 165 final StringBuffer buffer= new StringBuffer (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 184 public static Map getArgumentMap(final RefactoringDescriptor descriptor) { 185 Map 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 215 private static void readRefactoringDescriptorProxies(final IFileStore store, final String project, final Collection collection, final long start, final long end, final IProgressMonitor monitor, final String 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 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 exception) { 228 throw createCoreException(exception); 229 } finally { 230 monitor.worked(1); 231 if (stream != null) { 232 try { 233 stream.close(); 234 } catch (IOException exception) { 235 } 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 277 public static RefactoringDescriptorProxy[] readRefactoringDescriptorProxies(final InputStream stream, final String project, final long start, final long end) throws IOException { 278 final List list= new ArrayList (); 279 final BufferedReader reader= new BufferedReader (new InputStreamReader (stream, IRefactoringSerializationConstants.OUTPUT_ENCODING)); 280 while (reader.ready()) { 281 final String 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 (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 exception) { 290 } 292 } 293 } 294 } 295 return (RefactoringDescriptorProxy[]) list.toArray(new RefactoringDescriptorProxy[list.size()]); 296 } 297 298 310 public static RefactoringDescriptor[] readRefactoringDescriptors(final InputStream stream) throws CoreException { 311 final List list= new ArrayList (64); 312 readRefactoringDescriptors(stream, list, new NullProgressMonitor()); 313 return (RefactoringDescriptor[]) list.toArray(new RefactoringDescriptor[list.size()]); 314 } 315 316 328 private static void readRefactoringDescriptors(final InputStream stream, final Collection 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 (new BufferedInputStream (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 352 private static void removeIndexTree(final IFileStore store, final IProgressMonitor monitor, final String 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 394 public static void sortRefactoringDescriptorsAscending(final RefactoringDescriptor[] descriptors) { 395 Arrays.sort(descriptors, new Comparator () { 396 397 public final int compare(final Object first, final Object 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 417 public static void sortRefactoringDescriptorsAscending(final RefactoringDescriptorProxy[] proxies) { 418 Arrays.sort(proxies, new Comparator () { 419 420 public final int compare(final Object first, final Object 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 440 public static void sortRefactoringDescriptorsDescending(final RefactoringDescriptorProxy[] proxies) { 441 Arrays.sort(proxies, new Comparator () { 442 443 public final int compare(final Object first, final Object 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 464 public static IPath stampToPath(final long stamp) { 465 fgCalendar.setTimeInMillis(stamp); 466 final StringBuffer buffer= new StringBuffer (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 487 private static Document 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 id= descriptor.getID(); 493 transformer.beginRefactoring(id, descriptor.getTimeStamp(), descriptor.getProject(), descriptor.getDescription(), descriptor.getComment(), descriptor.getFlags()); 494 final Map arguments= getArgumentMap(descriptor); 495 if (arguments != null) { 496 checkArgumentMap(arguments); 497 for (final Iterator iterator= arguments.entrySet().iterator(); iterator.hasNext();) { 498 final Map.Entry entry= (Entry) iterator.next(); 499 transformer.createArgument((String ) entry.getKey(), (String ) entry.getValue()); 500 } 501 } 502 } finally { 503 transformer.endRefactoring(); 504 } 505 } finally { 506 transformer.endSession(); 507 } 508 return transformer.getResult(); 509 } 510 511 518 public static String unescapeString(final String string) { 519 if (string.indexOf(DELIMITER_COMPONENT) < 0) { 520 final int length= string.length(); 521 final StringBuffer buffer= new StringBuffer (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 557 private static void writeIndexEntry(final IFileStore file, final RefactoringDescriptorProxy[] proxies, final int flags, final IProgressMonitor monitor, final String task) throws CoreException, IOException { 558 OutputStream 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 (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 exception) { 570 } 572 } 573 } 574 } 575 576 586 public static void writeRefactoringDescriptorProxies(final OutputStream stream, final RefactoringDescriptorProxy[] proxies) throws IOException { 587 final StringBuffer buffer= new StringBuffer (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 602 private static final class DOMWriter extends PrintWriter { 603 604 private int tab; 605 606 607 private static final String XML_VERSION= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; 609 614 public DOMWriter(Writer output) { 615 super(output); 616 tab= 0; 617 } 618 619 public void printDocument(Document doc) { 620 println(XML_VERSION); 621 printElement(doc.getDocumentElement()); 622 } 623 624 629 public void printElement(Element element) { 630 boolean hasChildren= element.hasChildNodes(); 634 startTag(element, hasChildren); 635 if (hasChildren) { 636 tab++; 637 boolean prevWasText= false; 638 NodeList children= element.getChildNodes(); 639 for (int i= 0; i < children.getLength(); i++) { 640 Node node= children.item(i); 641 if (node instanceof Element ) { 642 if (!prevWasText) { 643 println(); 644 printTabulation(); 645 } 646 printElement((Element ) children.item(i)); 647 prevWasText= false; 648 } else if (node instanceof Text ) { 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 668 } 671 672 private void startTag(Element element, boolean hasChildren) { 673 StringBuffer sb= new StringBuffer (); 674 sb.append("<"); sb.append(element.getTagName()); 676 NamedNodeMap attributes= element.getAttributes(); 677 for (int i= 0; i < attributes.getLength(); i++) { 678 Attr attribute= (Attr ) attributes.item(i); 679 sb.append(" "); sb.append(attribute.getName()); 681 sb.append("=\""); sb.append(getEscaped(String.valueOf(attribute.getValue()))); 683 sb.append("\""); } 685 sb.append(hasChildren ? ">" : "/>"); print(sb.toString()); 687 } 688 689 private void endTag(Element element) { 690 StringBuffer sb= new StringBuffer (); 691 sb.append("</"); sb.append(element.getNodeName()); 693 sb.append(">"); print(sb.toString()); 695 } 696 697 private static void appendEscapedChar(StringBuffer buffer, char c) { 698 String 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 getEscaped(String s) { 709 StringBuffer result= new StringBuffer (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 getReplacement(char c) { 717 switch (c) { 723 case '<': 724 return "lt"; case '>': 726 return "gt"; case '"': 728 return "quot"; case '\'': 730 return "apos"; case '&': 732 return "amp"; case '\r': 734 return "#x0D"; case '\n': 736 return "#x0A"; case '\u0009': 738 return "#x09"; } 740 return null; 741 } 742 } 743 744 758 public static void writeRefactoringSession(final OutputStream 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 arguments= getArgumentMap(current); 770 if (arguments != null) { 771 checkArgumentMap(arguments); 772 for (final Iterator iterator= arguments.entrySet().iterator(); iterator.hasNext();) { 773 final Map.Entry entry= (Entry) iterator.next(); 774 transformer.createArgument((String ) entry.getKey(), (String ) entry.getValue()); 775 } 776 } 777 } finally { 778 transformer.endRefactoring(); 779 } 780 } 781 } 782 } finally { 783 transformer.endSession(); 784 } 785 final Document result= transformer.getResult(); 786 writeNode(stream, result); 787 } 788 789 private static void writeNode(final OutputStream stream, Document document) { 790 OutputStreamWriter outputStreamWriter= new OutputStreamWriter (stream, Charset.forName("UTF-8")); DOMWriter writer= new DOMWriter(outputStreamWriter); 792 writer.printDocument(document); 793 writer.flush(); 794 } 795 796 797 private RefactoringSessionDescriptor fCachedDescriptor= null; 798 799 800 private Document fCachedDocument= null; 801 802 803 private IPath fCachedPath= null; 804 805 806 private IFileStore fCachedStore= null; 807 808 809 private final IFileStore fHistoryStore; 810 811 815 private final String fProjectName; 816 817 826 RefactoringHistoryManager(final IFileStore store, final String name) { 827 Assert.isNotNull(store); 828 Assert.isTrue(name == null || !"".equals(name)); fHistoryStore= store; 830 fProjectName= name; 831 } 832 833 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 input= null; 860 try { 861 input= new BufferedInputStream (history.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); 862 final Document document= getCachedDocument(path, input); 863 try { 864 input.close(); 865 input= null; 866 } catch (IOException exception) { 867 } 869 monitor.worked(1); 870 final Document result= transformDescriptor(descriptor, false); 871 if (result != null) { 872 boolean found= false; 873 final NodeList list= result.getElementsByTagName(IRefactoringSerializationConstants.ELEMENT_REFACTORING); 874 final Element root= document.getDocumentElement(); 875 if (sort) { 876 final String string= Long.toString(stamp); 877 for (int offset= 0; offset < list.getLength(); offset++) { 878 final Element element= (Element ) list.item(offset); 879 final String 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 set= new HashSet (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 exception) { 900 throw createCoreException(exception); 901 } catch (IOException exception) { 902 throw createCoreException(exception); 903 } catch (SAXException exception) { 904 throw createCoreException(exception); 905 } finally { 906 if (input != null) { 907 try { 908 input.close(); 909 } catch (IOException exception) { 910 } 912 } 913 } 914 } else { 915 try { 916 final Document 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 exception) { 920 throw createCoreException(exception); 921 } 922 } 923 } 924 } finally { 925 monitor.done(); 926 } 927 } 928 929 944 private Document getCachedDocument(final IPath path, final InputStream input) throws SAXException , IOException , ParserConfigurationException { 945 if (path.equals(fCachedPath) && fCachedDocument != null) 946 return fCachedDocument; 947 final Document document= DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource (input)); 948 fCachedDocument= document; 949 fCachedPath= path; 950 return document; 951 } 952 953 964 private RefactoringSessionDescriptor getCachedSession(final IFileStore store, final InputStream input) throws CoreException { 965 if (store.equals(fCachedStore) && fCachedDescriptor != null) 966 return fCachedDescriptor; 967 final RefactoringSessionDescriptor descriptor= new RefactoringSessionReader(true).readSession(new InputSource (input)); 968 fCachedDescriptor= descriptor; 969 fCachedStore= store; 970 return descriptor; 971 } 972 973 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 set= new HashSet (); 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 1023 private void removeRefactoringDescriptors(final RefactoringDescriptorProxy[] proxies, final IPath path, final IProgressMonitor monitor, final String 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 resultingProxies= new HashSet (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 input= null; 1037 Document document= null; 1038 try { 1039 input= new BufferedInputStream (history.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 1, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); 1040 document= getCachedDocument(path, input); 1041 } catch (ParserConfigurationException exception) { 1042 throw createCoreException(exception); 1043 } catch (IOException exception) { 1044 throw createCoreException(exception); 1045 } catch (SAXException exception) { 1046 throw createCoreException(exception); 1047 } finally { 1048 if (input != null) { 1049 try { 1050 input.close(); 1051 } catch (IOException exception) { 1052 } 1054 } 1055 } 1056 final Set removedNodes= new HashSet (proxies.length); 1057 final NodeList list= document.getElementsByTagName(IRefactoringSerializationConstants.ELEMENT_REFACTORING); 1058 final int length= list.getLength(); 1059 for (int offset= 0; offset < length; offset++) { 1060 final Node node= list.item(offset); 1061 final NamedNodeMap attributes= node.getAttributes(); 1062 if (attributes != null) { 1063 final Node item= attributes.getNamedItem(IRefactoringSerializationConstants.ATTRIBUTE_STAMP); 1064 if (item != null) { 1065 final String 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 iterator= removedNodes.iterator(); iterator.hasNext();) { 1080 final Node node= (Node ) 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 exception) { 1087 throw createCoreException(exception); 1088 } 1089 } 1090 } 1091 } 1092 } finally { 1093 monitor.done(); 1094 } 1095 } 1096 1097 1109 void removeRefactoringDescriptors(final RefactoringDescriptorProxy[] proxies, final IProgressMonitor monitor, final String task) throws CoreException { 1110 try { 1111 final Map paths= new HashMap (); 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 collection= (Collection ) paths.get(path); 1116 if (collection == null) { 1117 collection= new ArrayList (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 entries= paths.entrySet(); 1125 subMonitor.beginTask(task, entries.size()); 1126 for (final Iterator iterator= entries.iterator(); iterator.hasNext();) { 1127 final Map.Entry entry= (Map.Entry ) iterator.next(); 1128 final Collection collection= (Collection ) 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 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 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 (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 } finally { 1175 try { 1176 if (input != null) 1177 input.close(); 1178 } catch (IOException exception) { 1179 } 1181 } 1182 } 1183 } finally { 1184 monitor.done(); 1185 } 1186 return null; 1187 } 1188 1189 1201 void setComment(final RefactoringDescriptorProxy proxy, final String 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 input= null; 1211 try { 1212 input= new BufferedInputStream (history.openInputStream(EFS.NONE, new SubProgressMonitor(monitor, 40, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL))); 1213 final Document document= getCachedDocument(path, input); 1214 try { 1215 input.close(); 1216 input= null; 1217 } catch (IOException exception) { 1218 } 1220 final String time= String.valueOf(stamp); 1221 final NodeList list= document.getElementsByTagName(IRefactoringSerializationConstants.ELEMENT_REFACTORING); 1222 for (int index= 0; index < list.getLength(); index++) { 1223 final Element element= (Element ) 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 exception) { 1231 throw createCoreException(exception); 1232 } catch (IOException exception) { 1233 throw createCoreException(exception); 1234 } catch (SAXException exception) { 1235 throw createCoreException(exception); 1236 } finally { 1237 if (input != null) { 1238 try { 1239 input.close(); 1240 } catch (IOException exception) { 1241 } 1243 } 1244 } 1245 } 1246 } 1247 } finally { 1248 monitor.done(); 1249 } 1250 } 1251 1252 1266 private void writeHistoryEntry(final IFileStore file, final Document document, final IProgressMonitor monitor, final String task) throws CoreException { 1267 OutputStream 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 (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 exception) { 1282 } 1284 } 1285 monitor.done(); 1286 } 1287 } 1288} 1289 | Popular Tags |