1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.io.File ; 22 import java.io.Reader ; 23 import java.io.FileReader ; 24 import java.io.IOException ; 25 import java.io.BufferedReader ; 26 import java.io.FileInputStream ; 27 import java.io.InputStreamReader ; 28 import java.util.Vector ; 29 import java.util.Enumeration ; 30 import java.util.NoSuchElementException ; 31 import org.apache.tools.ant.Project; 32 import org.apache.tools.ant.BuildException; 33 import org.apache.tools.ant.DirectoryScanner; 34 import org.apache.tools.ant.filters.FixCrLfFilter; 35 import org.apache.tools.ant.filters.ChainableReader; 36 import org.apache.tools.ant.types.FilterChain; 37 import org.apache.tools.ant.types.EnumeratedAttribute; 38 import org.apache.tools.ant.util.FileUtils; 39 40 83 84 public class FixCRLF extends MatchingTask implements ChainableReader { 85 86 87 public static final String ERROR_FILE_AND_SRCDIR 88 = "srcdir and file are mutually exclusive"; 89 90 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); 91 92 private boolean preserveLastModified = false; 93 private File srcDir; 94 private File destDir = null; 95 private File file; 96 private FixCrLfFilter filter = new FixCrLfFilter(); 97 private Vector fcv = null; 98 99 102 private String encoding = null; 103 104 107 private String outputEncoding = null; 108 109 115 public final Reader chain(final Reader rdr) { 116 return filter.chain(rdr); 117 } 118 119 123 public void setSrcdir(File srcDir) { 124 this.srcDir = srcDir; 125 } 126 127 132 public void setDestdir(File destDir) { 133 this.destDir = destDir; 134 } 135 136 140 public void setJavafiles(boolean javafiles) { 141 filter.setJavafiles(javafiles); 142 } 143 144 149 public void setFile(File file) { 150 this.file = file; 151 } 152 153 164 public void setEol(CrLf attr) { 165 filter.setEol(FixCrLfFilter.CrLf.newInstance(attr.getValue())); 166 } 167 168 181 public void setCr(AddAsisRemove attr) { 182 log("DEPRECATED: The cr attribute has been deprecated,", 183 Project.MSG_WARN); 184 log("Please use the eol attribute instead", Project.MSG_WARN); 185 String option = attr.getValue(); 186 CrLf c = new CrLf(); 187 if (option.equals("remove")) { 188 c.setValue("lf"); 189 } else if (option.equals("asis")) { 190 c.setValue("asis"); 191 } else { 192 c.setValue("crlf"); 194 } 195 setEol(c); 196 } 197 198 208 public void setTab(AddAsisRemove attr) { 209 filter.setTab(FixCrLfFilter.AddAsisRemove.newInstance(attr.getValue())); 210 } 211 212 218 public void setTablength(int tlength) throws BuildException { 219 try { 220 filter.setTablength(tlength); 221 } catch (IOException e) { 222 throw new BuildException(e); 223 } 224 } 225 226 236 public void setEof(AddAsisRemove attr) { 237 filter.setEof(FixCrLfFilter.AddAsisRemove.newInstance(attr.getValue())); 238 } 239 240 245 public void setEncoding(String encoding) { 246 this.encoding = encoding; 247 } 248 249 254 public void setOutputEncoding(String outputEncoding) { 255 this.outputEncoding = outputEncoding; 256 } 257 258 263 public void setFixlast(boolean fixlast) { 264 filter.setFixlast(fixlast); 265 } 266 267 272 public void setPreserveLastModified(boolean preserve) { 273 preserveLastModified = preserve; 274 } 275 276 280 public void execute() throws BuildException { 281 validate(); 283 284 String enc = encoding == null ? "default" : encoding; 286 log("options:" 287 + " eol=" + filter.getEol().getValue() 288 + " tab=" + filter.getTab().getValue() 289 + " eof=" + filter.getEof().getValue() 290 + " tablength=" + filter.getTablength() 291 + " encoding=" + enc 292 + " outputencoding=" 293 + (outputEncoding == null ? enc : outputEncoding), 294 Project.MSG_VERBOSE); 295 296 DirectoryScanner ds = super.getDirectoryScanner(srcDir); 297 String [] files = ds.getIncludedFiles(); 298 299 for (int i = 0; i < files.length; i++) { 300 processFile(files[i]); 301 } 302 } 303 304 private void validate() throws BuildException { 305 if (file != null) { 306 if (srcDir != null) { 307 throw new BuildException(ERROR_FILE_AND_SRCDIR); 308 } 309 fileset.setFile(file); 311 srcDir = file.getParentFile(); 313 } 314 if (srcDir == null) { 315 throw new BuildException("srcdir attribute must be set!"); 316 } 317 if (!srcDir.exists()) { 318 throw new BuildException("srcdir does not exist!"); 319 } 320 if (!srcDir.isDirectory()) { 321 throw new BuildException("srcdir is not a directory!"); 322 } 323 if (destDir != null) { 324 if (!destDir.exists()) { 325 throw new BuildException("destdir does not exist!"); 326 } 327 if (!destDir.isDirectory()) { 328 throw new BuildException("destdir is not a directory!"); 329 } 330 } 331 } 332 333 private void processFile(String file) throws BuildException { 334 File srcFile = new File (srcDir, file); 335 long lastModified = srcFile.lastModified(); 336 File destD = destDir == null ? srcDir : destDir; 337 338 if (fcv == null) { 339 FilterChain fc = new FilterChain(); 340 fc.add(filter); 341 fcv = new Vector (1); 342 fcv.add(fc); 343 } 344 File tmpFile = FILE_UTILS.createTempFile("fixcrlf", "", null); 345 tmpFile.deleteOnExit(); 346 try { 347 FILE_UTILS.copyFile(srcFile, tmpFile, null, fcv, false, false, 348 encoding, outputEncoding == null ? encoding : outputEncoding, 349 getProject()); 350 351 File destFile = new File (destD, file); 352 353 boolean destIsWrong = true; 354 if (destFile.exists()) { 355 log("destFile exists", Project.MSG_DEBUG); 357 destIsWrong = !FILE_UTILS.contentEquals(destFile, tmpFile); 358 log(destFile + (destIsWrong ? " is being written" 359 : " is not written, as the contents are identical"), 360 Project.MSG_DEBUG); 361 } 362 if (destIsWrong) { 363 FILE_UTILS.rename(tmpFile, destFile); 364 if (preserveLastModified) { 365 log("preserved lastModified", Project.MSG_DEBUG); 366 FILE_UTILS.setFileLastModified(destFile, lastModified); 367 } 368 tmpFile = null; 369 } 370 } catch (IOException e) { 371 throw new BuildException(e); 372 } 373 } 374 375 379 protected class OneLiner implements Enumeration { 380 private static final int UNDEF = -1; 381 private static final int NOTJAVA = 0; 382 private static final int LOOKING = 1; 383 private static final int INBUFLEN = 8192; 384 private static final int LINEBUFLEN = 200; 385 private static final char CTRLZ = '\u001A'; 386 387 private int state = filter.getJavafiles() ? LOOKING : NOTJAVA; 388 389 private StringBuffer eolStr = new StringBuffer (LINEBUFLEN); 390 private StringBuffer eofStr = new StringBuffer (); 391 392 private BufferedReader reader; 393 private StringBuffer line = new StringBuffer (); 394 private boolean reachedEof = false; 395 private File srcFile; 396 397 402 public OneLiner(File srcFile) 403 throws BuildException { 404 this.srcFile = srcFile; 405 try { 406 reader = new BufferedReader ( 407 ((encoding == null) ? new FileReader (srcFile) 408 : new InputStreamReader ( 409 new FileInputStream (srcFile), encoding)), INBUFLEN); 410 411 nextLine(); 412 } catch (IOException e) { 413 throw new BuildException(srcFile + ": " + e.getMessage(), 414 e, getLocation()); 415 } 416 } 417 418 422 protected void nextLine() 423 throws BuildException { 424 int ch = -1; 425 int eolcount = 0; 426 427 eolStr = new StringBuffer (); 428 line = new StringBuffer (); 429 430 try { 431 ch = reader.read(); 432 while (ch != -1 && ch != '\r' && ch != '\n') { 433 line.append((char) ch); 434 ch = reader.read(); 435 } 436 437 if (ch == -1 && line.length() == 0) { 438 reachedEof = true; 440 return; 441 } 442 443 switch ((char) ch) { 444 case '\r': 445 ++eolcount; 448 eolStr.append('\r'); 449 reader.mark(2); 450 ch = reader.read(); 451 switch (ch) { 452 case '\r': 453 ch = reader.read(); 454 if ((char) (ch) == '\n') { 455 eolcount += 2; 456 eolStr.append("\r\n"); 457 } else { 458 reader.reset(); 459 } 460 break; 461 case '\n': 462 ++eolcount; 463 eolStr.append('\n'); 464 break; 465 case -1: 466 break; 469 default: 470 reader.reset(); 471 break; 472 } break; 474 475 case '\n': 476 ++eolcount; 477 eolStr.append('\n'); 478 break; 479 default: 480 } 483 if (eolcount == 0) { 486 int i = line.length(); 487 while (--i >= 0 && line.charAt(i) == CTRLZ) { 488 } 490 if (i < line.length() - 1) { 491 eofStr.append(line.toString().substring(i + 1)); 494 if (i < 0) { 495 line.setLength(0); 496 reachedEof = true; 497 } else { 498 line.setLength(i + 1); 499 } 500 } 501 502 } 504 } catch (IOException e) { 505 throw new BuildException(srcFile + ": " + e.getMessage(), 506 e, getLocation()); 507 } 508 } 509 510 514 public String getEofStr() { 515 return eofStr.substring(0); 516 } 517 518 522 public int getState() { 523 return state; 524 } 525 526 530 public void setState(int state) { 531 this.state = state; 532 } 533 534 537 public boolean hasMoreElements() { 538 return !reachedEof; 539 } 540 541 546 public Object nextElement() 547 throws NoSuchElementException { 548 if (!hasMoreElements()) { 549 throw new NoSuchElementException ("OneLiner"); 550 } 551 BufferLine tmpLine = 552 new BufferLine(line.toString(), eolStr.substring(0)); 553 nextLine(); 554 return tmpLine; 555 } 556 557 561 public void close() throws IOException { 562 if (reader != null) { 563 reader.close(); 564 } 565 } 566 567 class BufferLine { 568 private int next = 0; 569 private int column = 0; 570 private int lookahead = UNDEF; 571 private String line; 572 private String eolStr; 573 574 public BufferLine(String line, String eolStr) 575 throws BuildException { 576 next = 0; 577 column = 0; 578 this.line = line; 579 this.eolStr = eolStr; 580 } 581 582 public int getNext() { 583 return next; 584 } 585 586 public void setNext(int next) { 587 this.next = next; 588 } 589 590 public int getLookahead() { 591 return lookahead; 592 } 593 594 public void setLookahead(int lookahead) { 595 this.lookahead = lookahead; 596 } 597 598 public char getChar(int i) { 599 return line.charAt(i); 600 } 601 602 public char getNextChar() { 603 return getChar(next); 604 } 605 606 public char getNextCharInc() { 607 return getChar(next++); 608 } 609 610 public int getColumn() { 611 return column; 612 } 613 614 public void setColumn(int col) { 615 column = col; 616 } 617 618 public int incColumn() { 619 return column++; 620 } 621 622 public int length() { 623 return line.length(); 624 } 625 626 public int getEolLength() { 627 return eolStr.length(); 628 } 629 630 public String getLineString() { 631 return line; 632 } 633 634 public String getEol() { 635 return eolStr; 636 } 637 638 public String substring(int begin) { 639 return line.substring(begin); 640 } 641 642 public String substring(int begin, int end) { 643 return line.substring(begin, end); 644 } 645 646 public void setState(int state) { 647 OneLiner.this.setState(state); 648 } 649 650 public int getState() { 651 return OneLiner.this.getState(); 652 } 653 } 654 } 655 656 659 public static class AddAsisRemove extends EnumeratedAttribute { 660 661 public String [] getValues() { 662 return new String [] {"add", "asis", "remove"}; 663 } 664 } 665 666 669 public static class CrLf extends EnumeratedAttribute { 670 673 674 public String [] getValues() { 675 return new String [] {"asis", "cr", "lf", "crlf", 676 "mac", "unix", "dos"}; 677 } 678 } 679 680 } 681 682 | Popular Tags |