1 package org.unicode.cldr.util; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.io.PrintWriter; 8 import java.io.Writer; 9 import java.util.Random; 10 11 import org.unicode.cldr.draft.FileUtilities; 12 13 import com.ibm.icu.util.ICUUncheckedIOException; 14 15 /** 16 * Simple utility to create a temporary file, write into it, then close it. 17 * If the file differs from the old file (except for date), then it is deleted. 18 * Otherwise it replaces the target file. Moved from UnicodeTools. 19 * @author markdavis 20 */ 21 public class TempPrintWriter extends Writer { 22 final PrintWriter tempPrintWriter; 23 final String tempName; 24 final String filename; 25 boolean noReplace = false; 26 27 28 public static TempPrintWriter openUTF8Writer(String filename) { 29 return new TempPrintWriter(new File(filename)); 30 } 31 32 public static TempPrintWriter openUTF8Writer(String dir, String filename) { 33 return new TempPrintWriter(new File(dir, filename)); 34 } 35 36 public TempPrintWriter(String dir, String filename) { 37 this(new File(dir, filename)); 38 } 39 40 public TempPrintWriter(File file) { 41 super(); 42 final String parentFile = file.getParent(); 43 this.filename = file.toString(); 44 Random rand = new Random(); 45 try { 46 File tempFile; 47 do { 48 tempFile = new File(parentFile, (0xFFFF & rand.nextInt()) + "-" + file.getName()); 49 } while (tempFile.exists()); 50 tempName = tempFile.toString(); 51 tempPrintWriter = FileUtilities.openUTF8Writer(parentFile, tempFile.getName()); 52 } catch (IOException e) { 53 throw new ICUUncheckedIOException(e); 54 } 55 } 56 57 public void dontReplaceFile() { 58 noReplace = true; 59 } 60 61 @Override 62 public void close() { 63 tempPrintWriter.close(); 64 try { 65 if (noReplace) { 66 new File(tempName).delete(); 67 } else { 68 replaceDifferentOrDelete(filename, tempName, false); 69 } 70 } catch (IOException e) { 71 throw new ICUUncheckedIOException(e); 72 } 73 } 74 75 @Override 76 public void write(char[] cbuf, int off, int len) { 77 tempPrintWriter.write(cbuf, off, len); 78 } 79 80 @Override 81 public void flush() { 82 tempPrintWriter.flush(); 83 } 84 85 public void println(Object line) { 86 tempPrintWriter.println(line); 87 } 88 89 public void print(Object line) { 90 tempPrintWriter.print(line); 91 } 92 93 public void println() { 94 tempPrintWriter.println(); 95 } 96 97 /** 98 * If contents(newFile) ≠ contents(oldFile), rename newFile to old. Otherwise delete newfile. Return true if replaced. * 99 */ 100 private static boolean replaceDifferentOrDelete(String oldFile, String newFile, boolean skipCopyright) throws IOException { 101 final File oldFile2 = new File(oldFile); 102 if (oldFile2.exists()) { 103 final String lines[] = new String[2]; 104 final boolean identical = filesAreIdentical(oldFile, newFile, skipCopyright, lines); 105 if (identical) { 106 new File(newFile).delete(); 107 return false; 108 } 109 System.out.println("Found difference in : " + oldFile + ", " + newFile); 110 final int diff = compare(lines[0], lines[1]); 111 System.out.println(" File1: '" + lines[0].substring(0,diff) + "', '" + lines[0].substring(diff) + "'"); 112 System.out.println(" File2: '" + lines[1].substring(0,diff) + "', '" + lines[1].substring(diff) + "'"); 113 } 114 new File(newFile).renameTo(oldFile2); 115 return true; 116 } 117 118 private static boolean filesAreIdentical(String file1, String file2, boolean skipCopyright, String[] lines) throws IOException { 119 if (file1 == null) { 120 lines[0] = null; 121 lines[1] = null; 122 return false; 123 } 124 final BufferedReader br1 = new BufferedReader(new FileReader(file1), 32*1024); 125 final BufferedReader br2 = new BufferedReader(new FileReader(file2), 32*1024); 126 String line1 = ""; 127 String line2 = ""; 128 try { 129 for (int lineCount = 0; ; ++lineCount) { 130 line1 = getLineWithoutFluff(br1, lineCount == 0, skipCopyright); 131 line2 = getLineWithoutFluff(br2, lineCount == 0, skipCopyright); 132 if (line1 == null) { 133 if (line2 == null) { 134 return true; 135 } 136 break; 137 } 138 if (!line1.equals(line2)) { 139 break; 140 } 141 } 142 lines[0] = line1; 143 lines[1] = line2; 144 if (lines[0] == null) { 145 lines[0] = "<end of file>"; 146 } 147 if (lines[1] == null) { 148 lines[1] = "<end of file>"; 149 } 150 return false; 151 } finally { 152 br1.close(); 153 br2.close(); 154 } 155 } 156 157 private static String getLineWithoutFluff(BufferedReader br1, boolean first, boolean skipCopyright) throws IOException { 158 while (true) { 159 String line1 = br1.readLine(); 160 if (line1 == null) { 161 return line1; 162 } 163 line1 = line1.trim(); 164 if (line1.length() == 0) { 165 continue; 166 } 167 if (line1.equals("#")) { 168 continue; 169 } 170 if (line1.startsWith("# Generated")) { 171 continue; 172 } 173 if (line1.startsWith("# Date")) { 174 continue; 175 } 176 if (skipCopyright && line1.startsWith("# Copyright")) { 177 continue; 178 } 179 if (line1.startsWith("<p><b>Date:</b>")) { 180 continue; 181 } 182 if (line1.startsWith("<td valign=\"top\">20") && line1.endsWith("GMT</td>")) { 183 continue; 184 } 185 186 if (line1.equals("# ================================================")) { 187 continue; 188 } 189 if (first && line1.startsWith("#")) { 190 first = false; 191 continue; 192 } 193 return line1; 194 } 195 } 196 197 /** 198 * Returns -1 if strings are equal; otherwise the first position they are different at. 199 */ 200 public static int compare(String a, String b) { 201 int len = a.length(); 202 if (len > b.length()) { 203 len = b.length(); 204 } 205 for (int i = 0; i < len; ++i) { 206 if (a.charAt(i) != b.charAt(i)) { 207 return i; 208 } 209 } 210 if (a.length() != b.length()) { 211 return len; 212 } 213 return -1; 214 } 215 216 }