Browse Source

1. ExpandProperties filter introduced as envisioned by Steve.

2.  String readFully(Reader) added to FileUtils.java (main trunk revision 1.13)
3.  Doc changes
4.  Removed the attribute evaluateproperties from <loadfile> as it is no longer necessary.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271617 13f79535-47bb-0310-9956-ffa450edef68
master
Magesh Umasankar 23 years ago
parent
commit
43e62b81ff
8 changed files with 832 additions and 46 deletions
  1. +4
    -8
      proposal/sandbox/filterreaders/docs/manual/CoreTasks/loadfile.html
  2. +27
    -0
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/BaseFilterReader.java
  3. +142
    -0
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/ExpandProperties.java
  4. +24
    -21
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/util/ChainReaderHelper.java
  5. +1
    -17
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/taskdefs/LoadFile.java
  6. +1
    -0
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java
  7. +5
    -0
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/types/FilterChain.java
  8. +628
    -0
      proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/util/FileUtils.java

+ 4
- 8
proposal/sandbox/filterreaders/docs/manual/CoreTasks/loadfile.html View File

@@ -41,11 +41,6 @@
<td valign="top">Whether to halt the build on failure</td> <td valign="top">Whether to halt the build on failure</td>
<td align="center" valign="top">No, default "true"</td> <td align="center" valign="top">No, default "true"</td>
</tr> </tr>
<tr>
<td valign="top">evaluateProperties</td>
<td valign="top">flag to enable property evalation in the file</td>
<td align="center" valign="top">No, default "false"</td>
</tr>
</table> </table>
<p> <p>
The LoadFile task supports nested <a href="../CoreTypes/filterreaderset.html"> The LoadFile task supports nested <a href="../CoreTypes/filterreaderset.html">
@@ -75,7 +70,7 @@ Load a file, don't fail if it is missing (a message is printed, though)
property="mail.recipients" property="mail.recipients"
srcFile="recipientlist.txt"&gt; srcFile="recipientlist.txt"&gt;
&lt;filterchain&gt; &lt;filterchain&gt;
&lt;filterreader classname="org.apache.tools.ant.filters.<a href="../CoreTypes/filterchain.html#StripLineBreaks">StripLineBreaks</a>" /&gt;
&lt;<a href="../CoreTypes/filterchain.html#striplinebreaks">striplinebreaks</a>/&gt;
&lt;/filterchaint&gt; &lt;/filterchaint&gt;
&lt;/loadfile&gt; &lt;/loadfile&gt;
</pre> </pre>
@@ -84,8 +79,9 @@ merging lines to ensure this happens.


<pre> &lt;loadfile <pre> &lt;loadfile
property="system.configuration.xml" property="system.configuration.xml"
srcFile="configuration.xml"
evaluateProperties="true" /&gt;
srcFile="configuration.xml"&gt;
&lt;<a href="../CoreTypes/filterchain.html#expandproperties">expandproperties</a>/&gt;
&lt;/loadfile&gt;
</pre> </pre>
Load an XML file into a property, expanding all properties declared Load an XML file into a property, expanding all properties declared
in the file in the process. in the file in the process.


+ 27
- 0
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/BaseFilterReader.java View File

@@ -58,6 +58,9 @@ import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;


import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.FileUtils;

/** /**
* Base class for core filter readers. * Base class for core filter readers.
* *
@@ -69,6 +72,9 @@ public abstract class BaseFilterReader
/** Have the parameters passed been interpreted? */ /** Have the parameters passed been interpreted? */
private boolean initialized = false; private boolean initialized = false;


/** The Ant project */
private Project project = null;

/** /**
* This constructor is a dummy constructor and is * This constructor is a dummy constructor and is
* not meant to be used by any class other than Ant's * not meant to be used by any class other than Ant's
@@ -162,6 +168,20 @@ public abstract class BaseFilterReader
return initialized; 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 * Read till EOL
*/ */
@@ -177,4 +197,11 @@ public abstract class BaseFilterReader
} }
return line; return line;
} }

/**
* Read till EOF
*/
protected final String readFully() throws IOException {
return FileUtils.readFully(in, 8192);
}
} }

+ 142
- 0
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/ExpandProperties.java View File

@@ -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
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.filters;

import java.io.IOException;
import java.io.Reader;

import org.apache.tools.ant.Project;

/**
* Attach a prefix to every line
*
* Example:
* =======
*
* &lt;prefixlines prefix=&quot;Foo&quot;/&gt;
*
* Or:
*
* &lt;filterreader classname=&quot;org.apache.tools.ant.filters.PrefixLines&quot;&gt;
* &lt;param name=&quot;prefix&quot; value=&quot;Foo&quot;/&gt;
* &lt;/filterreader&gt;
*
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
*/
public final class ExpandProperties
extends BaseFilterReader
implements ChainableReader
{
/** Data that must be read from, if not null. */
private String queuedData = null;

/**
* This constructor is a dummy constructor and is
* not meant to be used by any class other than Ant's
* introspection mechanism. This will close the filter
* that is created making it useless for further operations.
*/
public ExpandProperties() {
super();
}

/**
* Create a new filtered reader.
*
* @param in a Reader object providing the underlying stream.
*/
public ExpandProperties(final Reader in) {
super(in);
}

/**
* Prefix lines with user defined prefix.
*/
public final int read() throws IOException {

int ch = -1;

if (queuedData != null && queuedData.length() == 0) {
queuedData = null;
}

if (queuedData != null) {
ch = queuedData.charAt(0);
queuedData = queuedData.substring(1);
if (queuedData.length() == 0) {
queuedData = null;
}
} else {
queuedData = readFully();
if (queuedData == null) {
ch = -1;
} else {
Project project = getProject();
queuedData = project.replaceProperties(queuedData);
return read();
}
}
return ch;
}

/**
* Create a new PrefixLines using the passed in
* Reader for instantiation.
*/
public final Reader chain(final Reader rdr) {
ExpandProperties newFilter = new ExpandProperties(rdr);
newFilter.setProject(getProject());
return newFilter;
}
}

+ 24
- 21
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/filters/util/ChainReaderHelper.java View File

@@ -56,12 +56,14 @@ package org.apache.tools.ant.filters.util;
import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project; import org.apache.tools.ant.Project;
import org.apache.tools.ant.filters.BaseFilterReader;
import org.apache.tools.ant.filters.ChainableReader; import org.apache.tools.ant.filters.ChainableReader;
import org.apache.tools.ant.types.AntFilterReader; import org.apache.tools.ant.types.AntFilterReader;
import org.apache.tools.ant.types.FilterChain; import org.apache.tools.ant.types.FilterChain;
import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Parameter; import org.apache.tools.ant.types.Parameter;
import org.apache.tools.ant.types.Parameterizable; import org.apache.tools.ant.types.Parameterizable;
import org.apache.tools.ant.util.FileUtils;


import java.io.*; import java.io.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@@ -84,13 +86,16 @@ public final class ChainReaderHelper {
/** /**
* The size of the buffer to be used. * The size of the buffer to be used.
*/ */
public int bufferSize = 4096;
public int bufferSize = 8192;


/** /**
* Chain of filters * Chain of filters
*/ */
public Vector filterChains = new Vector(); public Vector filterChains = new Vector();


/** The Ant project */
private Project project = null;

/** /**
* Sets the primary reader * Sets the primary reader
*/ */
@@ -98,6 +103,20 @@ public final class ChainReaderHelper {
primaryReader = rdr; primaryReader = rdr;
} }


/**
* Set the project to work with
*/
public final void setProject(final Project project) {
this.project = project;
}

/**
* Get the project
*/
public final Project getProject() {
return project;
}

/** /**
* Sets the buffer size to be used. Defaults to 4096, * Sets the buffer size to be used. Defaults to 4096,
* if this method is not invoked. * if this method is not invoked.
@@ -194,6 +213,9 @@ public final class ChainReaderHelper {
} }
} else if (o instanceof ChainableReader && } else if (o instanceof ChainableReader &&
o instanceof Reader) { o instanceof Reader) {
if (project != null && o instanceof BaseFilterReader) {
((BaseFilterReader) o).setProject(project);
}
instream = ((ChainableReader) o).chain(instream); instream = ((ChainableReader) o).chain(instream);
} }
} }
@@ -207,25 +229,6 @@ public final class ChainReaderHelper {
*/ */
public final String readFully(Reader rdr) public final String readFully(Reader rdr)
throws IOException { 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;
return FileUtils.readFully(rdr, bufferSize);
} }
} }

+ 1
- 17
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/taskdefs/LoadFile.java View File

@@ -92,11 +92,6 @@ public final class LoadFile extends Task {
*/ */
private String property = null; private String property = null;


/**
* flag to control whether props get evaluated or not
*/
private boolean evaluateProperties=false;

/** /**
* Holds FilterChains * Holds FilterChains
*/ */
@@ -148,15 +143,6 @@ public final class LoadFile extends Task {
} }




/**
* setter to eval properties.
* @since 1.6
*/
public final void setEvaluateProperties(final boolean evaluateProperties) {
this.evaluateProperties=evaluateProperties;
}


/** /**
* read in a source file to a property * read in a source file to a property
* *
@@ -194,14 +180,12 @@ public final class LoadFile extends Task {
crh.setBufferSize(size); crh.setBufferSize(size);
crh.setPrimaryReader(instream); crh.setPrimaryReader(instream);
crh.setFilterChains(filterChains); crh.setFilterChains(filterChains);
crh.setProject(project);
instream = crh.getAssembledReader(); instream = crh.getAssembledReader();


String text = crh.readFully(instream); String text = crh.readFully(instream);


if (text != null) { if (text != null) {
if(evaluateProperties) {
text = project.replaceProperties(text);
}
project.setNewProperty(property, text); project.setNewProperty(property, text);
log("loaded " + text.length() + " characters",Project.MSG_VERBOSE); log("loaded " + text.length() + " characters",Project.MSG_VERBOSE);
log(property+" := "+text,Project.MSG_DEBUG); log(property+" := "+text,Project.MSG_DEBUG);


+ 1
- 0
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/taskdefs/LoadProperties.java View File

@@ -128,6 +128,7 @@ public final class LoadProperties extends Task {
crh.setBufferSize(size); crh.setBufferSize(size);
crh.setPrimaryReader(instream); crh.setPrimaryReader(instream);
crh.setFilterChains(filterChains); crh.setFilterChains(filterChains);
crh.setProject(project);
instream = crh.getAssembledReader(); instream = crh.getAssembledReader();


String text = crh.readFully(instream); String text = crh.readFully(instream);


+ 5
- 0
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/types/FilterChain.java View File

@@ -55,6 +55,7 @@ package org.apache.tools.ant.types;


import java.util.Vector; import java.util.Vector;


import org.apache.tools.ant.filters.ExpandProperties;
import org.apache.tools.ant.filters.HeadFilter; import org.apache.tools.ant.filters.HeadFilter;
import org.apache.tools.ant.filters.LineContains; import org.apache.tools.ant.filters.LineContains;
import org.apache.tools.ant.filters.PrefixLines; import org.apache.tools.ant.filters.PrefixLines;
@@ -82,6 +83,10 @@ public final class FilterChain {
return filterReaders; return filterReaders;
} }


public final void addExpandProperties(final ExpandProperties expandProperties) {
filterReaders.addElement(expandProperties);
}

public final void addHeadFilter(final HeadFilter headFilter) { public final void addHeadFilter(final HeadFilter headFilter) {
filterReaders.addElement(headFilter); filterReaders.addElement(headFilter);
} }


+ 628
- 0
proposal/sandbox/filterreaders/src/main/org/apache/tools/ant/util/FileUtils.java View File

@@ -0,0 +1,628 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;

import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.Random;
import java.util.Stack;
import java.util.StringTokenizer;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FilterSetCollection;

/**
* This class also encapsulates methods which allow Files to be
* refered to using abstract path names which are translated to native
* system file paths at runtime as well as copying files or setting
* there last modification time.
*
* @author duncan@x180.com
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a>
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*
* @version $Revision$
*/

public class FileUtils {
private static Random rand = new Random(System.currentTimeMillis());
private static Object lockReflection = new Object();
private static java.lang.reflect.Method setLastModified = null;

/**
* Factory method.
*/
public static FileUtils newFileUtils() {
return new FileUtils();
}

/**
* Empty constructor.
*/
protected FileUtils() {}

/**
* Convienence method to copy a file from a source to a destination.
* No filtering is performed.
*
* @throws IOException
*/
public void copyFile(String sourceFile, String destFile) throws IOException {
copyFile(new File(sourceFile), new File(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(String sourceFile, String destFile, FilterSetCollection filters)
throws IOException
{
copyFile(new File(sourceFile), new File(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(String sourceFile, String destFile, FilterSetCollection filters,
boolean overwrite) throws IOException {
copyFile(new File(sourceFile), new File(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 <code>destFile</code> file should be made equal
* to the last modified time of <code>sourceFile</code>.
*
* @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 <code>destFile</code> file should be made equal
* to the last modified time of <code>sourceFile</code>.
*
* @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
* &quot;./&quot; or &quot;../&quot; sequences (same for \ instead
* of /). If it is null, this call is equivalent to
* <code>new java.io.File(filename)</code>.
*
* @param filename a file name
*
* @return an absolute file that doesn't contain &quot;./&quot; or
* &quot;../&quot; 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());
}

/**
* &quot;normalize&quot; the given absolute path.
*
* <p>This includes:
* <ul>
* <li>Uppercase the drive letter if there is one.</li>
* <li>Remove redundant slashes after the drive spec.</li>
* <li>resolve all ./, .\, ../ and ..\ sequences.</li>
* <li>DOS style paths that start with a drive letter will have
* \ as the separator.</li>
* </ul>
*
* @throws java.lang.NullPointerException if the file path is
* equal to null.
*/
public File normalize(String path) {
String orig = path;

path = path.replace('/', File.separatorChar)
.replace('\\', File.separatorChar);

// make sure we are dealing with an absolute path
if (!path.startsWith(File.separator) &&
! (path.length() >= 2 &&
Character.isLetter(path.charAt(0)) &&
path.charAt(1) == ':')
) {
String msg = path + " is not an absolute path";
throw new BuildException(msg);
}

boolean dosWithDrive = false;
String root = null;
// Eliminate consecutive slashes after the drive spec
if (path.length() >= 2 &&
Character.isLetter(path.charAt(0)) &&
path.charAt(1) == ':') {

dosWithDrive = true;

char[] ca = path.replace('/', '\\').toCharArray();
StringBuffer sb = new StringBuffer();
sb.append(Character.toUpperCase(ca[0])).append(':');

for (int i = 2; i < ca.length; i++) {
if ((ca[i] != '\\') ||
(ca[i] == '\\' && ca[i - 1] != '\\')
) {
sb.append(ca[i]);
}
}

path = sb.toString().replace('\\', File.separatorChar);
if (path.length() == 2) {
root = path;
path = "";
} else {
root = path.substring(0, 3);
path = path.substring(3);
}

} else {
if (path.length() == 1) {
root = File.separator;
path = "";
} else if (path.charAt(1) == File.separatorChar) {
// UNC drive
root = File.separator+File.separator;
path = path.substring(2);
} else {
root = File.separator;
path = path.substring(1);
}
}

Stack s = new Stack();
s.push(root);
StringTokenizer tok = new StringTokenizer(path, File.separator);
while (tok.hasMoreTokens()) {
String thisToken = tok.nextToken();
if (".".equals(thisToken)) {
continue;
} else if ("..".equals(thisToken)) {
if (s.size() < 2) {
throw new BuildException("Cannot resolve path "+orig);
} else {
s.pop();
}
} else { // plain component
s.push(thisToken);
}
}

StringBuffer sb = new StringBuffer();
for (int i=0; i<s.size(); i++) {
if (i > 1) {
// not before the filesystem root and not after it, since root
// already contains one
sb.append(File.separatorChar);
}
sb.append(s.elementAt(i));
}


path = sb.toString();
if (dosWithDrive) {
path = path.replace('/', '\\');
}
return new File(path);
}

/**
* Create a temporary file in a given directory.
*
* <p>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.</p>
*
* <p>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.</p>
*
* @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.
*
* <p>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.</p>
*
* @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;
}
}


Loading…
Cancel
Save