/* * 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. *
* This task can take the following arguments: *
* When this task executes, it will scan the srcdir based on the include * and exclude properties. *
* 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. *
* Warning: do not run on binary files.
* Caution: 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 = "
*
*/
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:
*
*
*
* @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:
*
*
*/
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:
*
*
*/
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