diff --git a/proposal/sandbox/filterreaders/docs/manual/CoreTasks/loadfile.html b/proposal/sandbox/filterreaders/docs/manual/CoreTasks/loadfile.html index e909de3cf..06a2f0550 100644 --- a/proposal/sandbox/filterreaders/docs/manual/CoreTasks/loadfile.html +++ b/proposal/sandbox/filterreaders/docs/manual/CoreTasks/loadfile.html @@ -41,11 +41,6 @@
The LoadFile task supports nested @@ -75,7 +70,7 @@ Load a file, don't fail if it is missing (a message is printed, though) property="mail.recipients" srcFile="recipientlist.txt"> <filterchain> - <filterreader classname="org.apache.tools.ant.filters.StripLineBreaks" /> + <striplinebreaks/> </filterchaint> </loadfile> @@ -84,8 +79,9 @@ merging lines to ensure this happens.
<loadfile property="system.configuration.xml" - srcFile="configuration.xml" - evaluateProperties="true" /> + srcFile="configuration.xml"> + <expandproperties/> + </loadfile>Load an XML file into a property, expanding all properties declared in the file in the process. diff --git a/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/BaseFilterReader.java b/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/BaseFilterReader.java index 514313c4a..5ce041edb 100644 --- a/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/BaseFilterReader.java +++ b/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/BaseFilterReader.java @@ -58,6 +58,9 @@ import java.io.IOException; import java.io.Reader; import java.io.StringReader; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.util.FileUtils; + /** * Base class for core filter readers. * @@ -69,6 +72,9 @@ public abstract class BaseFilterReader /** Have the parameters passed been interpreted? */ private boolean initialized = false; + /** The Ant project */ + private Project project = null; + /** * This constructor is a dummy constructor and is * not meant to be used by any class other than Ant's @@ -162,6 +168,20 @@ public abstract class BaseFilterReader return initialized; } + /** + * Set the project to work with + */ + public final void setProject(final Project project) { + this.project = project; + } + + /** + * Get the project + */ + protected final Project getProject() { + return project; + } + /** * Read till EOL */ @@ -177,4 +197,11 @@ public abstract class BaseFilterReader } return line; } + + /** + * Read till EOF + */ + protected final String readFully() throws IOException { + return FileUtils.readFully(in, 8192); + } } diff --git a/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/ExpandProperties.java b/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/ExpandProperties.java new file mode 100644 index 000000000..13dfc54cc --- /dev/null +++ b/proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/ExpandProperties.java @@ -0,0 +1,142 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *
destFile
file should be made equal
+ * to the last modified time of sourceFile
.
+ *
+ * @throws IOException
+ */
+ public void copyFile(String sourceFile, String destFile, FilterSetCollection filters,
+ boolean overwrite, boolean preserveLastModified)
+ throws IOException {
+ copyFile(new File(sourceFile), new File(destFile), filters,
+ overwrite, preserveLastModified);
+ }
+
+ /**
+ * Convienence method to copy a file from a source to a destination.
+ * No filtering is performed.
+ *
+ * @throws IOException
+ */
+ public void copyFile(File sourceFile, File destFile) throws IOException {
+ copyFile(sourceFile, destFile, null, false, false);
+ }
+
+ /**
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used.
+ *
+ * @throws IOException
+ */
+ public void copyFile(File sourceFile, File destFile, FilterSetCollection filters)
+ throws IOException {
+ copyFile(sourceFile, destFile, filters, false, false);
+ }
+
+ /**
+ * Convienence method to copy a file from a source to a
+ * destination specifying if token filtering must be used and if
+ * source files may overwrite newer destination files.
+ *
+ * @throws IOException
+ */
+ public void copyFile(File sourceFile, File destFile, FilterSetCollection filters,
+ boolean overwrite) throws IOException {
+ copyFile(sourceFile, destFile, filters, overwrite, false);
+ }
+
+ /**
+ * Convienence method to copy a file from a source to a
+ * destination specifying if token filtering must be used, if
+ * source files may overwrite newer destination files and the
+ * last modified time of destFile
file should be made equal
+ * to the last modified time of sourceFile
.
+ *
+ * @throws IOException
+ */
+ public void copyFile(File sourceFile, File destFile, FilterSetCollection filters,
+ boolean overwrite, boolean preserveLastModified)
+ throws IOException {
+
+ if (overwrite || !destFile.exists() ||
+ destFile.lastModified() < sourceFile.lastModified()) {
+
+ if (destFile.exists() && destFile.isFile()) {
+ destFile.delete();
+ }
+
+ // ensure that parent dir of dest file exists!
+ // not using getParentFile method to stay 1.1 compat
+ File parent = getParentFile(destFile);
+ if (!parent.exists()) {
+ parent.mkdirs();
+ }
+
+ if (filters != null && filters.hasFilters()) {
+ BufferedReader in = new BufferedReader(new FileReader(sourceFile));
+ BufferedWriter out = new BufferedWriter(new FileWriter(destFile));
+
+ int length;
+ String newline = null;
+ String line = in.readLine();
+ while (line != null) {
+ if (line.length() == 0) {
+ out.newLine();
+ } else {
+ newline = filters.replaceTokens(line);
+ out.write(newline);
+ out.newLine();
+ }
+ line = in.readLine();
+ }
+
+ out.close();
+ in.close();
+ } else {
+ FileInputStream in = new FileInputStream(sourceFile);
+ FileOutputStream out = new FileOutputStream(destFile);
+
+ byte[] buffer = new byte[8 * 1024];
+ int count = 0;
+ do {
+ out.write(buffer, 0, count);
+ count = in.read(buffer, 0, buffer.length);
+ } while (count != -1);
+
+ in.close();
+ out.close();
+ }
+
+ if (preserveLastModified) {
+ setFileLastModified(destFile, sourceFile.lastModified());
+ }
+ }
+ }
+
+ /**
+ * see whether we have a setLastModified method in File and return it.
+ */
+ protected final Method getSetLastModified() {
+ if (Project.getJavaVersion() == Project.JAVA_1_1) {
+ return null;
+ }
+ if (setLastModified == null) {
+ synchronized (lockReflection) {
+ if (setLastModified == null) {
+ try {
+ setLastModified =
+ java.io.File.class.getMethod("setLastModified",
+ new Class[] {Long.TYPE});
+ } catch (NoSuchMethodException nse) {
+ throw new BuildException("File.setlastModified not in JDK > 1.1?",
+ nse);
+ }
+ }
+ }
+ }
+ return setLastModified;
+ }
+
+ /**
+ * Calls File.setLastModified(long time) in a Java 1.1 compatible way.
+ */
+ public void setFileLastModified(File file, long time) throws BuildException {
+ if (Project.getJavaVersion() == Project.JAVA_1_1) {
+ return;
+ }
+ Long[] times = new Long[1];
+ if (time < 0) {
+ times[0] = new Long(System.currentTimeMillis());
+ } else {
+ times[0] = new Long(time);
+ }
+
+ try {
+ getSetLastModified().invoke(file, times);
+ } catch (java.lang.reflect.InvocationTargetException ite) {
+ Throwable nested = ite.getTargetException();
+ throw new BuildException("Exception setting the modification time "
+ + "of " + file, nested);
+ } catch (Throwable other) {
+ throw new BuildException("Exception setting the modification time "
+ + "of " + file, other);
+ }
+ }
+
+ /**
+ * Interpret the filename as a file relative to the given file -
+ * unless the filename already represents an absolute filename.
+ *
+ * @param file the "reference" file for relative paths. This
+ * instance must be an absolute file and must not contain
+ * "./" or "../" sequences (same for \ instead
+ * of /). If it is null, this call is equivalent to
+ * new java.io.File(filename)
.
+ *
+ * @param filename a file name
+ *
+ * @return an absolute file that doesn't contain "./" or
+ * "../" sequences and uses the correct separator for
+ * the current platform.
+ */
+ public File resolveFile(File file, String filename) {
+ filename = filename.replace('/', File.separatorChar)
+ .replace('\\', File.separatorChar);
+
+ // deal with absolute files
+ if (filename.startsWith(File.separator) ||
+
+ (filename.length() >= 2 &&
+ Character.isLetter(filename.charAt(0)) &&
+ filename.charAt(1) == ':')
+
+ ) {
+ return normalize(filename);
+ }
+
+ if (file == null) {
+ return new File(filename);
+ }
+
+ File helpFile = new File(file.getAbsolutePath());
+ StringTokenizer tok = new StringTokenizer(filename, File.separator);
+ while (tok.hasMoreTokens()) {
+ String part = tok.nextToken();
+ if (part.equals("..")) {
+ helpFile = getParentFile(helpFile);
+ if (helpFile == null) {
+ String msg = "The file or path you specified ("
+ + filename + ") is invalid relative to "
+ + file.getPath();
+ throw new BuildException(msg);
+ }
+ } else if (part.equals(".")) {
+ // Do nothing here
+ } else {
+ helpFile = new File(helpFile, part);
+ }
+ }
+
+ return new File(helpFile.getAbsolutePath());
+ }
+
+ /**
+ * "normalize" the given absolute path.
+ *
+ * This includes: + *
The file denoted by the returned abstract pathname did not + * exist before this method was invoked, any subsequent invocation + * of this method will yield a different file name.
+ * + *This method is different to File.createTempFile of JDK 1.2 + * as it doesn't create the file itself and doesn't use platform + * specific temporary directory when the parentDir attribute is + * null.
+ * + * @param parentDir Directory to create the temporary file in - + * current working directory will be assumed if this parameter is + * null. + * + * @since 1.8 + */ + public File createTempFile(String prefix, String suffix, File parentDir) { + + File result = null; + String parent = null; + if (parentDir != null) { + parent = parentDir.getPath(); + } + DecimalFormat fmt = new DecimalFormat("#####"); + synchronized (rand) { + do { + result = new File(parent, + prefix + fmt.format(rand.nextInt()) + + suffix); + } while (result.exists()); + } + return result; + } + + /** + * Compares the contents of two files. + * + *simple but sub-optimal comparision algorithm. written for + * working rather than fast. Better would be a block read into + * buffers followed by long comparisions apart from the final 1-7 + * bytes.
+ * + * @since 1.9 + */ + public boolean contentEquals(File f1, File f2) throws IOException { + if (f1.exists() != f2.exists()) { + return false; + } + + if (!f1.exists()) { + // two not existing files are equal + return true; + } + + if (f1.isDirectory() || f2.isDirectory()) { + // don't want to compare directory contents for now + return false; + } + + if (f1.equals(f2)) { + // same filename => true + return true; + } + + if (f1.length() != f2.length()) { + // different size =>false + return false; + } + + InputStream in1 = null; + InputStream in2 = null; + try { + in1 = new BufferedInputStream(new FileInputStream(f1)); + in2 = new BufferedInputStream(new FileInputStream(f2)); + + int expectedByte = in1.read(); + while (expectedByte != -1) { + if (expectedByte != in2.read()) { + return false; + } + expectedByte = in1.read(); + } + if (in2.read() != -1) { + return false; + } + return true; + } finally { + if (in1 != null) { + try { + in1.close(); + } catch (IOException e) {} + } + if (in2 != null) { + try { + in2.close(); + } catch (IOException e) {} + } + } + } + + /** + * Emulation of File.getParentFile for JDK 1.1 + * + * @since 1.10 + */ + public File getParentFile(File f) { + if (f != null) { + String p = f.getParent(); + if (p != null) { + return new File(p); + } + } + return null; + } + + /** + * Read from reader till EOF + */ + public static final String readFully(Reader rdr) throws IOException { + return readFully(rdr, 8192); + } + + /** + * Read from reader till EOF + */ + public static final String readFully(Reader rdr, int bufferSize) throws IOException { + final char[] buffer = new char[bufferSize]; + int bufferLength = 0; + String text = null; + StringBuffer textBuffer = null; + while (bufferLength != -1) { + bufferLength = rdr.read(buffer); + if (bufferLength != -1) { + if (textBuffer == null) { + textBuffer = new StringBuffer( + new String(buffer, 0, bufferLength)); + } else { + textBuffer.append(new String(buffer, 0, bufferLength)); + } + } + } + if (textBuffer != null) { + text = textBuffer.toString(); + } + return text; + } +} +