diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java | 696 |
1 files changed, 696 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java new file mode 100644 index 00000000..465bf462 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/FixCRLF.java @@ -0,0 +1,696 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.taskdefs; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Enumeration; +import java.util.NoSuchElementException; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.filters.ChainableReader; +import org.apache.tools.ant.filters.FixCrLfFilter; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.FilterChain; +import org.apache.tools.ant.util.FileUtils; + +/** + * Converts text source files to local OS formatting conventions, as + * well as repair text files damaged by misconfigured or misguided editors or + * file transfer programs. + * <p> + * This task can take the following arguments: + * <ul> + * <li>srcdir + * <li>destdir + * <li>include + * <li>exclude + * <li>cr + * <li>eol + * <li>tab + * <li>eof + * <li>encoding + * <li>targetencoding + * </ul> + * Of these arguments, only <b>sourcedir</b> is required. + * <p> + * When this task executes, it will scan the srcdir based on the include + * and exclude properties. + * <p> + * This version generalises the handling of EOL characters, and allows + * for CR-only line endings (the standard on Mac systems prior to OS X). + * Tab handling has also been generalised to accommodate any tabwidth + * from 2 to 80, inclusive. Importantly, it will leave untouched any + * literal TAB characters embedded within string or character constants. + * <p> + * <em>Warning:</em> do not run on binary files. + * <em>Caution:</em> run with care on carefully formatted files. + * This may sound obvious, but if you don't specify asis, presume that + * your files are going to be modified. If "tabs" is "add" or "remove", + * whitespace characters may be added or removed as necessary. Similarly, + * for CR's - in fact "eol"="crlf" or cr="add" can result in cr + * characters being removed in one special case accommodated, i.e., + * CRCRLF is regarded as a single EOL to handle cases where other + * programs have converted CRLF into CRCRLF. + * + * @since Ant 1.1 + * + * @ant.task category="filesystem" + */ + +public class FixCRLF extends MatchingTask implements ChainableReader { + + private static final String FIXCRLF_ERROR = "<fixcrlf> error: "; + /** error string for using srcdir and file */ + public static final String ERROR_FILE_AND_SRCDIR + = FIXCRLF_ERROR + "srcdir and file are mutually exclusive"; + + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + private boolean preserveLastModified = false; + private File srcDir; + private File destDir = null; + private File file; + private FixCrLfFilter filter = new FixCrLfFilter(); + private Vector<FilterChain> fcv = null; + + /** + * Encoding to assume for the files + */ + private String encoding = null; + + /** + * Encoding to use for output files + */ + private String outputEncoding = null; + + + /** + * Chain this task as a reader. + * @param rdr Reader to chain. + * @return a Reader. + * @since Ant 1.7? + */ + public final Reader chain(final Reader rdr) { + return filter.chain(rdr); + } + + /** + * Set the source dir to find the source text files. + * @param srcDir the source directory. + */ + public void setSrcdir(File srcDir) { + this.srcDir = srcDir; + } + + /** + * Set the destination where the fixed files should be placed. + * Default is to replace the original file. + * @param destDir the destination directory. + */ + public void setDestdir(File destDir) { + this.destDir = destDir; + } + + /** + * Set to true if modifying Java source files. + * @param javafiles whether modifying Java files. + */ + public void setJavafiles(boolean javafiles) { + filter.setJavafiles(javafiles); + } + + /** + * Set a single file to convert. + * @since Ant 1.6.3 + * @param file the file to convert. + */ + public void setFile(File file) { + this.file = file; + } + + /** + * Specify how EndOfLine characters are to be handled. + * + * @param attr valid values: + * <ul> + * <li>asis: leave line endings alone + * <li>cr: convert line endings to CR + * <li>lf: convert line endings to LF + * <li>crlf: convert line endings to CRLF + * </ul> + */ + public void setEol(CrLf attr) { + filter.setEol(FixCrLfFilter.CrLf.newInstance(attr.getValue())); + } + + /** + * Specify how carriage return (CR) characters are to be handled. + * + * @param attr valid values: + * <ul> + * <li>add: ensure that there is a CR before every LF + * <li>asis: leave CR characters alone + * <li>remove: remove all CR characters + * </ul> + * + * @deprecated since 1.4.x. + * Use {@link #setEol setEol} instead. + */ + public void setCr(AddAsisRemove attr) { + log("DEPRECATED: The cr attribute has been deprecated,", + Project.MSG_WARN); + log("Please use the eol attribute instead", Project.MSG_WARN); + String option = attr.getValue(); + CrLf c = new CrLf(); + if (option.equals("remove")) { + c.setValue("lf"); + } else if (option.equals("asis")) { + c.setValue("asis"); + } else { + // must be "add" + c.setValue("crlf"); + } + setEol(c); + } + + /** + * Specify how tab characters are to be handled. + * + * @param attr valid values: + * <ul> + * <li>add: convert sequences of spaces which span a tab stop to tabs + * <li>asis: leave tab and space characters alone + * <li>remove: convert tabs to spaces + * </ul> + */ + public void setTab(AddAsisRemove attr) { + filter.setTab(FixCrLfFilter.AddAsisRemove.newInstance(attr.getValue())); + } + + /** + * Specify tab length in characters. + * + * @param tlength specify the length of tab in spaces. + * @throws BuildException on error. + */ + public void setTablength(int tlength) throws BuildException { + try { + filter.setTablength(tlength); + } catch (IOException e) { + // filter.setTablength throws IOException that would better be + // a BuildException + throw new BuildException(e.getMessage(), e); + } + } + + /** + * Specify how DOS EOF (control-z) characters are to be handled. + * + * @param attr valid values: + * <ul> + * <li>add: ensure that there is an eof at the end of the file + * <li>asis: leave eof characters alone + * <li>remove: remove any eof character found at the end + * </ul> + */ + public void setEof(AddAsisRemove attr) { + filter.setEof(FixCrLfFilter.AddAsisRemove.newInstance(attr.getValue())); + } + + /** + * Specifies the encoding Ant expects the files to be + * in--defaults to the platforms default encoding. + * @param encoding String encoding name. + */ + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * Specifies the encoding that the files are + * to be written in--same as input encoding by default. + * @param outputEncoding String outputEncoding name. + */ + public void setOutputEncoding(String outputEncoding) { + this.outputEncoding = outputEncoding; + } + + /** + * Specify whether a missing EOL will be added + * to the final line of a file. + * @param fixlast whether to fix the last line. + */ + public void setFixlast(boolean fixlast) { + filter.setFixlast(fixlast); + } + + /** + * Set whether to preserve the last modified time as the original files. + * @param preserve true if timestamps should be preserved. + * @since Ant 1.6.3 + */ + public void setPreserveLastModified(boolean preserve) { + preserveLastModified = preserve; + } + + /** + * Executes the task. + * @throws BuildException on error. + */ + public void execute() throws BuildException { + // first off, make sure that we've got a srcdir and destdir + validate(); + + // log options used + String enc = encoding == null ? "default" : encoding; + log("options:" + + " eol=" + filter.getEol().getValue() + + " tab=" + filter.getTab().getValue() + + " eof=" + filter.getEof().getValue() + + " tablength=" + filter.getTablength() + + " encoding=" + enc + + " outputencoding=" + + (outputEncoding == null ? enc : outputEncoding), + Project.MSG_VERBOSE); + + DirectoryScanner ds = super.getDirectoryScanner(srcDir); + String[] files = ds.getIncludedFiles(); + + for (int i = 0; i < files.length; i++) { + processFile(files[i]); + } + } + + private void validate() throws BuildException { + if (file != null) { + if (srcDir != null) { + throw new BuildException(ERROR_FILE_AND_SRCDIR); + } + //patch file into the fileset + fileset.setFile(file); + //set our parent dir + srcDir = file.getParentFile(); + } + if (srcDir == null) { + throw new BuildException( + FIXCRLF_ERROR + "srcdir attribute must be set!"); + } + if (!srcDir.exists()) { + throw new BuildException( + FIXCRLF_ERROR + "srcdir does not exist: '" + srcDir + "'"); + } + if (!srcDir.isDirectory()) { + throw new BuildException( + FIXCRLF_ERROR + "srcdir is not a directory: '" + srcDir + "'"); + } + if (destDir != null) { + if (!destDir.exists()) { + throw new BuildException( + FIXCRLF_ERROR + "destdir does not exist: '" + + destDir + "'"); + } + if (!destDir.isDirectory()) { + throw new BuildException( + FIXCRLF_ERROR + "destdir is not a directory: '" + + destDir + "'"); + } + } + } + + private void processFile(String file) throws BuildException { + File srcFile = new File(srcDir, file); + long lastModified = srcFile.lastModified(); + File destD = destDir == null ? srcDir : destDir; + + if (fcv == null) { + FilterChain fc = new FilterChain(); + fc.add(filter); + fcv = new Vector<FilterChain>(1); + fcv.add(fc); + } + File tmpFile = FILE_UTILS.createTempFile("fixcrlf", "", null, true, true); + try { + FILE_UTILS.copyFile(srcFile, tmpFile, null, fcv, true, false, + encoding, outputEncoding == null ? encoding : outputEncoding, + getProject()); + + File destFile = new File(destD, file); + + boolean destIsWrong = true; + if (destFile.exists()) { + // Compare the destination with the temp file + log("destFile " + destFile + " exists", Project.MSG_DEBUG); + destIsWrong = !FILE_UTILS.contentEquals(destFile, tmpFile); + log(destFile + (destIsWrong ? " is being written" + : " is not written, as the contents are identical"), + Project.MSG_DEBUG); + } + if (destIsWrong) { + FILE_UTILS.rename(tmpFile, destFile); + if (preserveLastModified) { + log("preserved lastModified for " + destFile, + Project.MSG_DEBUG); + FILE_UTILS.setFileLastModified(destFile, lastModified); + } + } + } catch (IOException e) { + throw new BuildException("error running fixcrlf on file " + srcFile, e); + } finally { + if (tmpFile != null && tmpFile.exists()) { + FILE_UTILS.tryHardToDelete(tmpFile); + } + } + } + + /** + * Deprecated, the functionality has been moved to filters.FixCrLfFilter. + * @deprecated since 1.7.0. + */ + protected class OneLiner implements Enumeration<Object> { + private static final int UNDEF = -1; + private static final int NOTJAVA = 0; + private static final int LOOKING = 1; + private static final int INBUFLEN = 8192; + private static final int LINEBUFLEN = 200; + private static final char CTRLZ = '\u001A'; + + private int state = filter.getJavafiles() ? LOOKING : NOTJAVA; + + private StringBuffer eolStr = new StringBuffer(LINEBUFLEN); + private StringBuffer eofStr = new StringBuffer(); + + private BufferedReader reader; + private StringBuffer line = new StringBuffer(); + private boolean reachedEof = false; + private File srcFile; + + /** + * Constructor. + * @param srcFile the file to read. + * @throws BuildException if there is an error. + */ + public OneLiner(File srcFile) + throws BuildException { + this.srcFile = srcFile; + try { + reader = new BufferedReader( + ((encoding == null) ? new FileReader(srcFile) + : new InputStreamReader( + new FileInputStream(srcFile), encoding)), INBUFLEN); + + nextLine(); + } catch (IOException e) { + throw new BuildException(srcFile + ": " + e.getMessage(), + e, getLocation()); + } + } + + /** + * Move to the next line. + * @throws BuildException if there is an error. + */ + protected void nextLine() + throws BuildException { + int ch = -1; + int eolcount = 0; + + eolStr = new StringBuffer(); + line = new StringBuffer(); + + try { + ch = reader.read(); + while (ch != -1 && ch != '\r' && ch != '\n') { + line.append((char) ch); + ch = reader.read(); + } + + if (ch == -1 && line.length() == 0) { + // Eof has been reached + reachedEof = true; + return; + } + + switch ((char) ch) { + case '\r': + // Check for \r, \r\n and \r\r\n + // Regard \r\r not followed by \n as two lines + ++eolcount; + eolStr.append('\r'); + reader.mark(2); + ch = reader.read(); + switch (ch) { + case '\r': + ch = reader.read(); + if ((char) (ch) == '\n') { + eolcount += 2; + eolStr.append("\r\n"); + } else { + reader.reset(); + } + break; + case '\n': + ++eolcount; + eolStr.append('\n'); + break; + case -1: + // don't reposition when we've reached the end + // of the stream + break; + default: + reader.reset(); + break; + } // end of switch ((char)(ch = reader.read())) + break; + + case '\n': + ++eolcount; + eolStr.append('\n'); + break; + default: + // Fall tru + } // end of switch ((char) ch) + + // if at eolcount == 0 and trailing characters of string + // are CTRL-Zs, set eofStr + if (eolcount == 0) { + int i = line.length(); + while (--i >= 0 && line.charAt(i) == CTRLZ) { + // keep searching for the first ^Z + } + if (i < line.length() - 1) { + // Trailing characters are ^Zs + // Construct new line and eofStr + eofStr.append(line.toString().substring(i + 1)); + if (i < 0) { + line.setLength(0); + reachedEof = true; + } else { + line.setLength(i + 1); + } + } + + } // end of if (eolcount == 0) + + } catch (IOException e) { + throw new BuildException(srcFile + ": " + e.getMessage(), + e, getLocation()); + } + } + + /** + * get the eof string. + * @return the eof string. + */ + public String getEofStr() { + return eofStr.substring(0); + } + + /** + * get the state. + * @return the state. + */ + public int getState() { + return state; + } + + /** + * Set the state. + * @param state the value to use. + */ + public void setState(int state) { + this.state = state; + } + + /** + * @return true if there is more elements. + */ + public boolean hasMoreElements() { + return !reachedEof; + } + + /** + * get the next element. + * @return the next element. + * @throws NoSuchElementException if there is no more. + */ + public Object nextElement() + throws NoSuchElementException { + if (!hasMoreElements()) { + throw new NoSuchElementException("OneLiner"); + } + BufferLine tmpLine = + new BufferLine(line.toString(), eolStr.substring(0)); + nextLine(); + return tmpLine; + } + + /** + * Close the reader. + * @throws IOException if there is an error. + */ + public void close() throws IOException { + if (reader != null) { + reader.close(); + } + } + + class BufferLine { + private int next = 0; + private int column = 0; + private int lookahead = UNDEF; + private String line; + private String eolStr; + + public BufferLine(String line, String eolStr) + throws BuildException { + next = 0; + column = 0; + this.line = line; + this.eolStr = eolStr; + } + + public int getNext() { + return next; + } + + public void setNext(int next) { + this.next = next; + } + + public int getLookahead() { + return lookahead; + } + + public void setLookahead(int lookahead) { + this.lookahead = lookahead; + } + + public char getChar(int i) { + return line.charAt(i); + } + + public char getNextChar() { + return getChar(next); + } + + public char getNextCharInc() { + return getChar(next++); + } + + public int getColumn() { + return column; + } + + public void setColumn(int col) { + column = col; + } + + public int incColumn() { + return column++; + } + + public int length() { + return line.length(); + } + + public int getEolLength() { + return eolStr.length(); + } + + public String getLineString() { + return line; + } + + public String getEol() { + return eolStr; + } + + public String substring(int begin) { + return line.substring(begin); + } + + public String substring(int begin, int end) { + return line.substring(begin, end); + } + + public void setState(int state) { + OneLiner.this.setState(state); + } + + public int getState() { + return OneLiner.this.getState(); + } + } + } + + /** + * Enumerated attribute with the values "asis", "add" and "remove". + */ + public static class AddAsisRemove extends EnumeratedAttribute { + /** {@inheritDoc}. */ + public String[] getValues() { + return new String[] {"add", "asis", "remove"}; + } + } + + /** + * Enumerated attribute with the values "asis", "cr", "lf" and "crlf". + */ + public static class CrLf extends EnumeratedAttribute { + /** + * @see EnumeratedAttribute#getValues + */ + /** {@inheritDoc}. */ + public String[] getValues() { + return new String[] {"asis", "cr", "lf", "crlf", + "mac", "unix", "dos"}; + } + } + +} + |