1 19 20 package org.netbeans.modules.diff.cmdline; 21 22 import java.io.*; 23 import java.util.ArrayList ; 24 import java.util.List ; 25 import java.util.regex.Pattern ; 26 import java.util.regex.PatternSyntaxException ; 27 28 import org.openide.filesystems.FileObject; 29 import org.openide.filesystems.FileUtil; 30 import org.openide.util.NbBundle; 31 import org.openide.util.Utilities; 32 33 import org.netbeans.api.diff.Difference; 34 import org.netbeans.spi.diff.DiffProvider; 35 import org.openide.ErrorManager; 36 37 45 public class CmdlineDiffProvider extends DiffProvider implements java.io.Serializable { 46 47 public static final String DIFF_REGEXP = "(^[0-9]+(,[0-9]+|)[d][0-9]+$)|"+ 49 "(^[0-9]+(,[0-9]+|)[c][0-9]+(,[0-9]+|)$)|"+ 50 "(^[0-9]+[a][0-9]+(,[0-9]+|)$)"; 51 private static final int BUFF_LENGTH = 1024; 52 53 private String diffCmd; 54 private transient Pattern pattern; 55 58 static final long serialVersionUID =4101521743158176210L; 59 63 public CmdlineDiffProvider(String diffCmd) { 64 this.diffCmd = diffCmd; 65 try { 66 pattern = Pattern.compile(DIFF_REGEXP); 67 } catch (PatternSyntaxException resex) {} 68 } 71 72 public static CmdlineDiffProvider createDefault() { 73 return new CmdlineDiffProvider("diff {0} {1}"); } 75 76 81 public void setDiffCommand(String diffCmd) { 82 this.diffCmd = diffCmd; 83 } 84 85 88 public String getDiffCommand() { 89 return diffCmd; 90 } 91 92 private static boolean checkEmpty(String str, String element) { 93 if (str == null || str.length() == 0) { 94 100 return true; 102 } 103 return false; 104 } 105 106 109 public String getDisplayName() { 110 return NbBundle.getMessage(CmdlineDiffProvider.class, "displayName"); 111 } 112 113 116 public String getShortDescription() { 117 return NbBundle.getMessage(CmdlineDiffProvider.class, "shortDescription"); 118 } 119 120 127 public Difference[] computeDiff(Reader r1, Reader r2) throws IOException { 128 File f1 = null; 129 File f2 = null; 130 try { 131 f1 = FileUtil.normalizeFile(File.createTempFile("TempDiff".intern(), null)); 132 f2 = FileUtil.normalizeFile(File.createTempFile("TempDiff".intern(), null)); 133 FileWriter fw1 = new FileWriter(f1); 134 FileWriter fw2 = new FileWriter(f2); 135 char[] buffer = new char[BUFF_LENGTH]; 136 int length; 137 while((length = r1.read(buffer)) > 0) fw1.write(buffer, 0, length); 138 while((length = r2.read(buffer)) > 0) fw2.write(buffer, 0, length); 139 r1.close(); 140 r2.close(); 141 fw1.close(); 142 fw2.close(); 143 return createDiff(f1, f2); 144 } finally { 145 if (f1 != null) f1.delete(); 146 if (f2 != null) f2.delete(); 147 } 148 } 149 150 157 public Difference[] computeDiff(FileObject fo1, FileObject fo2) throws IOException { 158 File f1 = FileUtil.toFile(fo1); 159 File f2 = FileUtil.toFile(fo2); 160 if (f1 != null && f2 != null) { 161 return createDiff(f1, f2); 162 } else { 163 return null; 164 } 165 } 166 167 170 private Difference[] createDiff(File f1, File f2) throws IOException { 171 final StringBuffer firstText = new StringBuffer (); 172 final StringBuffer secondText = new StringBuffer (); 173 if (pattern == null) { 174 try { 175 pattern = Pattern.compile(DIFF_REGEXP); 176 } catch (PatternSyntaxException resex) { 177 throw (IOException) ErrorManager.getDefault().annotate( 178 new IOException(), resex.getLocalizedMessage()); 179 } 180 } 183 diffCmd = diffCmd.replace("\"{0}\"", "{0}").replace("\"{1}\"", "{1}"); String firstPath; 185 String secondPath; 186 if (Utilities.isWindows()) { 187 firstPath = "\"" + f1.getAbsolutePath() + "\""; secondPath = "\"" + f2.getAbsolutePath() + "\""; } else { 190 firstPath = f1.getAbsolutePath(); 191 secondPath = f2.getAbsolutePath(); 192 } 193 final String cmd = java.text.MessageFormat.format(diffCmd, firstPath, secondPath); 194 195 final Process p[] = new Process [1]; 196 final Object [] ret = new Object [1]; 197 Runnable cancellableProcessWrapper = new Runnable () { 198 public void run() { 199 try { 200 ErrorManager.getDefault().log("#69616 CDP: executing: " + cmd); synchronized(p) { 202 p[0] = Runtime.getRuntime().exec(cmd); 203 } 204 Reader stdout = new InputStreamReader(p[0].getInputStream()); 205 char[] buffer = new char[BUFF_LENGTH]; 206 StringBuffer outBuffer = new StringBuffer (); 207 int length; 208 List <Difference> differences = new ArrayList <Difference>(); 209 while ((length = stdout.read(buffer)) > 0) { 210 for (int i = 0; i < length; i++) { 211 if (buffer[i] == '\n') { 212 outputLine(outBuffer.toString(), pattern, differences, 214 firstText, secondText); 215 outBuffer.delete(0, outBuffer.length()); 216 } else { 217 if (buffer[i] != 13) { 218 outBuffer.append(buffer[i]); 219 } 220 } 221 } 222 } 223 if (outBuffer.length() > 0) outputLine(outBuffer.toString(), pattern, differences, 224 firstText, secondText); 225 setTextOnLastDifference(differences, firstText, secondText); 226 ret[0] = differences.toArray(new Difference[differences.size()]); 227 } catch (IOException ioex) { 228 ret[0] = (IOException) ErrorManager.getDefault().annotate(ioex, 229 NbBundle.getMessage(CmdlineDiffProvider.class, "runtimeError", cmd)); 230 } 231 } 232 }; 233 234 Thread t = new Thread (cancellableProcessWrapper, "Diff.exec()"); t.start(); 236 try { 237 t.join(); 238 synchronized(ret) { 239 if (ret[0] instanceof IOException) { 240 throw (IOException) ret[0]; 241 } 242 return (Difference[]) ret[0]; 243 } 244 } catch (InterruptedException e) { 245 synchronized(p[0]) { 246 p[0].destroy(); 247 } 248 throw new InterruptedIOException(); 249 } 250 251 } 252 253 public static void setTextOnLastDifference(List <Difference> differences, 254 StringBuffer firstText, StringBuffer secondText) { 255 if (differences.size() > 0) { 256 String t1 = firstText.toString(); 257 if (t1.length() == 0) t1 = null; 258 String t2 = secondText.toString(); 259 if (t2.length() == 0) t2 = null; 260 Difference d = (Difference) differences.remove(differences.size() - 1); 261 differences.add(new Difference(d.getType(), d.getFirstStart(), d.getFirstEnd(), 262 d.getSecondStart(), d.getSecondEnd(), t1, t2)); 263 firstText.delete(0, firstText.length()); 264 secondText.delete(0, secondText.length()); 265 } 266 } 267 268 272 public static void outputLine(String elements, Pattern pattern, List <Difference> differences, 274 StringBuffer firstText, StringBuffer secondText) { 275 279 int index = 0, commaIndex = 0; 280 int n1 = 0, n2 = 0, n3 = 0, n4 = 0; 281 String nStr; 282 if (pattern.matcher(elements).matches()) { 283 setTextOnLastDifference(differences, firstText, secondText); 284 } else { 285 if (elements.startsWith("< ")) { 286 firstText.append(elements.substring(2) + "\n"); 287 } 288 if (elements.startsWith("> ")) { 289 secondText.append(elements.substring(2) + "\n"); 290 } 291 return ; 292 } 293 if ((index = elements.indexOf('a')) >= 0) { 294 try { 296 n1 = Integer.parseInt(elements.substring(0, index)); 297 index++; 298 commaIndex = elements.indexOf(',', index); 299 if (commaIndex < 0) { 300 nStr = elements.substring(index, elements.length()); 301 if (checkEmpty(nStr, elements)) return; 302 n3 = Integer.parseInt(nStr); 303 n4 = n3; 304 } else { 305 nStr = elements.substring(index, commaIndex); 306 if (checkEmpty(nStr, elements)) return; 307 n3 = Integer.parseInt(nStr); 308 nStr = elements.substring(commaIndex+1, elements.length()); 309 if (nStr == null || nStr.length() == 0) n4 = n3; 310 else n4 = Integer.parseInt(nStr); 311 } 312 } catch (NumberFormatException e) { 313 319 return; 321 } 322 differences.add(new Difference(Difference.ADD, n1, 0, n3, n4)); 325 } else if ((index = elements.indexOf('d')) >= 0) { 326 commaIndex = elements.lastIndexOf(',', index); 328 try { 329 if (commaIndex < 0) { 330 n1 = Integer.parseInt(elements.substring(0, index)); 331 n2 = n1; 332 } else { 333 nStr = elements.substring(0, commaIndex); 334 if (checkEmpty(nStr, elements)) return; 335 n1 = Integer.parseInt(nStr); 336 nStr = elements.substring(commaIndex+1, index); 337 if (checkEmpty(nStr, elements)) return; 338 n2 = Integer.parseInt(nStr); 339 } 340 nStr = elements.substring(index+1, elements.length()); 341 if (checkEmpty(nStr, elements)) return; 342 n3 = Integer.parseInt(nStr); 343 } catch (NumberFormatException e) { 344 350 return; 352 } 353 differences.add(new Difference(Difference.DELETE, n1, n2, n3, 0)); 356 } else if ((index = elements.indexOf('c')) >= 0) { 357 commaIndex = elements.lastIndexOf(',', index); 359 try { 360 if (commaIndex < 0) { 361 n1 = Integer.parseInt(elements.substring(0, index)); 362 n2 = n1; 363 } else { 364 nStr = elements.substring(0, commaIndex); 365 if (checkEmpty(nStr, elements)) return; 366 n1 = Integer.parseInt(nStr); 367 nStr = elements.substring(commaIndex+1, index); 368 if (checkEmpty(nStr, elements)) return; 369 n2 = Integer.parseInt(nStr); 370 } 371 index++; 372 commaIndex = elements.indexOf(',', index); 373 if (commaIndex < 0) { 374 nStr = elements.substring(index, elements.length()); 375 if (checkEmpty(nStr, elements)) return; 376 n3 = Integer.parseInt(nStr); 377 n4 = n3; 378 } else { 379 nStr = elements.substring(index, commaIndex); 380 if (checkEmpty(nStr, elements)) return; 381 n3 = Integer.parseInt(nStr); 382 nStr = elements.substring(commaIndex+1, elements.length()); 383 if (nStr == null || nStr.length() == 0) n4 = n3; 384 else n4 = Integer.parseInt(nStr); 385 } 386 } catch (NumberFormatException e) { 387 393 return; 395 } 396 differences.add(new Difference(Difference.CHANGE, n1, n2, n3, n4)); 399 } 400 } 401 402 } 403 | Popular Tags |