git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@292553 13f79535-47bb-0310-9956-ffa450edef68master
@@ -20,7 +20,7 @@ import java.io.IOException; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.ResourceUtils; | |||
/** | |||
* Compares Resources by content. | |||
@@ -60,7 +60,7 @@ public class Content extends ResourceComparator { | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
try { | |||
return FileUtils.getFileUtils().compareContent(foo, bar, !binary); | |||
return ResourceUtils.compareContent(foo, bar, !binary); | |||
} catch (IOException e) { | |||
throw new BuildException(e); | |||
} | |||
@@ -38,6 +38,7 @@ import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.resources.selectors.ResourceSelector; | |||
import org.apache.tools.ant.types.selectors.BaseExtendSelector; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.ResourceUtils; | |||
/** | |||
@@ -540,7 +541,7 @@ public class ModifiedSelector extends BaseExtendSelector | |||
FileUtils fu = FileUtils.getFileUtils(); | |||
File tmpFile = fu.createTempFile("modified-", ".tmp", null); | |||
Resource tmpResource = new FileResource(tmpFile); | |||
fu.copyResource(resource, tmpResource); | |||
ResourceUtils.copyResource(resource, tmpResource); | |||
boolean isSelected = isSelected(tmpFile.getParentFile(), | |||
tmpFile.getName(), | |||
resource.toLongString()); | |||
@@ -41,9 +41,7 @@ import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.filters.util.ChainReaderHelper; | |||
import org.apache.tools.ant.taskdefs.condition.Os; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.FilterSetCollection; | |||
import org.apache.tools.ant.types.resources.Touchable; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.launch.Locator; | |||
@@ -54,7 +52,6 @@ import org.apache.tools.ant.launch.Locator; | |||
* their last modification time. | |||
* | |||
*/ | |||
public class FileUtils { | |||
private static final FileUtils PRIMARY_INSTANCE = new FileUtils(); | |||
@@ -68,7 +65,7 @@ public class FileUtils { | |||
private static boolean onWin9x = Os.isFamily("win9x"); | |||
private static boolean onWindows = Os.isFamily("windows"); | |||
private static final int BUF_SIZE = 8192; | |||
static final int BUF_SIZE = 8192; | |||
// for toURI | |||
private static boolean[] isSpecial = new boolean[256]; | |||
@@ -520,206 +517,12 @@ public class FileUtils { | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
copyResource(new FileResource(sourceFile), new FileResource(destFile), | |||
ResourceUtils.copyResource( | |||
new FileResource(sourceFile), new FileResource(destFile), | |||
filters, filterChains, overwrite, preserveLastModified, | |||
inputEncoding, outputEncoding, project); | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another. | |||
* No filtering is performed. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public void copyResource(Resource source, Resource dest) throws IOException { | |||
copyResource(source, dest, null); | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another. | |||
* No filtering is performed. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public void copyResource(Resource source, Resource dest, Project project) | |||
throws IOException { | |||
copyResource(source, dest, null, null, false, | |||
false, null, null, project); | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another | |||
* specifying whether token filtering must be used, whether filter chains | |||
* must be used, whether newer destination files may be overwritten and | |||
* whether the last modified time of <code>dest</code> file should be made | |||
* equal to the last modified time of <code>source</code>. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param filters the collection of filters to apply to this copy. | |||
* @param filterChains filterChains to apply during the copy. | |||
* @param overwrite Whether or not the destination Resource should be | |||
* overwritten if it already exists. | |||
* @param preserveLastModified Whether or not the last modified time of | |||
* the destination Resource should be set to that | |||
* of the source. | |||
* @param inputEncoding the encoding used to read the files. | |||
* @param outputEncoding the encoding used to write the files. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public void copyResource(Resource source, Resource dest, | |||
FilterSetCollection filters, Vector filterChains, | |||
boolean overwrite, boolean preserveLastModified, | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
if (!overwrite) { | |||
long slm = source.getLastModified(); | |||
if (dest.isExists() && slm != 0 | |||
&& dest.getLastModified() > slm) { | |||
return; | |||
} | |||
} | |||
final boolean filterSetsAvailable = (filters != null | |||
&& filters.hasFilters()); | |||
final boolean filterChainsAvailable = (filterChains != null | |||
&& filterChains.size() > 0); | |||
if (filterSetsAvailable) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
InputStreamReader isr = null; | |||
if (inputEncoding == null) { | |||
isr = new InputStreamReader(source.getInputStream()); | |||
} else { | |||
isr = new InputStreamReader(source.getInputStream(), | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
LineTokenizer lineTokenizer = new LineTokenizer(); | |||
lineTokenizer.setIncludeDelims(true); | |||
String newline = null; | |||
String line = lineTokenizer.getToken(in); | |||
while (line != null) { | |||
if (line.length() == 0) { | |||
// this should not happen, because the lines are | |||
// returned with the end of line delimiter | |||
out.newLine(); | |||
} else { | |||
newline = filters.replaceTokens(line); | |||
out.write(newline); | |||
} | |||
line = lineTokenizer.getToken(in); | |||
} | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
} else if (filterChainsAvailable | |||
|| (inputEncoding != null | |||
&& !inputEncoding.equals(outputEncoding)) | |||
|| (inputEncoding == null && outputEncoding != null)) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
InputStreamReader isr = null; | |||
if (inputEncoding == null) { | |||
isr = new InputStreamReader(source.getInputStream()); | |||
} else { | |||
isr = new InputStreamReader(source.getInputStream(), | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
char[] buffer = new char[BUF_SIZE]; | |||
while (true) { | |||
int nRead = in.read(buffer, 0, buffer.length); | |||
if (nRead == -1) { | |||
break; | |||
} | |||
out.write(buffer, 0, nRead); | |||
} | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
} else { | |||
InputStream in = null; | |||
OutputStream out = null; | |||
try { | |||
in = source.getInputStream(); | |||
out = dest.getOutputStream(); | |||
byte[] buffer = new byte[BUF_SIZE]; | |||
int count = 0; | |||
do { | |||
out.write(buffer, 0, count); | |||
count = in.read(buffer, 0, buffer.length); | |||
} while (count != -1); | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
} | |||
if (preserveLastModified && dest instanceof Touchable) { | |||
setLastModified((Touchable) dest, source.getLastModified()); | |||
} | |||
} | |||
/** | |||
* Calls File.setLastModified(long time). Originally written to | |||
* to dynamically bind to that call on Java1.2+. | |||
@@ -729,19 +532,7 @@ public class FileUtils { | |||
* if this is -1, the current time is used. | |||
*/ | |||
public void setFileLastModified(File file, long time) { | |||
setLastModified(new FileResource(file), time); | |||
} | |||
/** | |||
* Set the last modified time of an object implementing | |||
* org.apache.tools.ant.types.resources.Touchable . | |||
* | |||
* @param t the Touchable whose modified time is to be set. | |||
* @param time the time to which the last modified time is to be set. | |||
* if this is -1, the current time is used. | |||
*/ | |||
public void setLastModified(Touchable t, long time) { | |||
t.touch((time < 0) ? System.currentTimeMillis() : time); | |||
ResourceUtils.setLastModified(new FileResource(file), time); | |||
} | |||
/** | |||
@@ -897,6 +688,7 @@ public class FileUtils { | |||
* @param path the path to dissect. | |||
* @return String[] {root, remaining path}. | |||
* @throws java.lang.NullPointerException if path is null. | |||
* @since Ant 1.7 | |||
*/ | |||
public String[] dissect(String path) { | |||
char sep = File.separatorChar; | |||
@@ -1063,143 +855,8 @@ public class FileUtils { | |||
* @since Ant 1.6.3 | |||
*/ | |||
public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { | |||
return contentEquals(new FileResource(f1), new FileResource(f2), textfile); | |||
} | |||
/** | |||
* Compares the contents of two Resources. | |||
* | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @param text true if the content is to be treated as text and | |||
* differences in kind of line break are to be ignored. | |||
* | |||
* @return true if the content of the Resources is the same. | |||
* | |||
* @throws IOException if the Resources cannot be read. | |||
* @since Ant 1.6.3 | |||
*/ | |||
public boolean contentEquals(Resource r1, Resource r2, boolean text) throws IOException { | |||
if (r1.isExists() != r2.isExists()) { | |||
return false; | |||
} | |||
if (!r1.isExists()) { | |||
// two not existing files are equal | |||
return true; | |||
} | |||
// should the following two be switched? If r1 and r2 refer to the same file, | |||
// isn't their content equal regardless of whether that file is a directory? | |||
if (r1.isDirectory() || r2.isDirectory()) { | |||
// don't want to compare directory contents for now | |||
return false; | |||
} | |||
if (r1.equals(r2)) { | |||
return true; | |||
} | |||
if (!text && r1.getSize() != r2.getSize()) { | |||
return false; | |||
} | |||
return compareContent(r1, r2, text) == 0; | |||
} | |||
/** | |||
* Compare the content of two Resources. A nonexistent Resource's | |||
* content is "less than" that of an existing Resource; a directory-type | |||
* Resource's content is "less than" that of a file-type Resource. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @param text true if the content is to be treated as text and | |||
* differences in kind of line break are to be ignored. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
*/ | |||
public int compareContent(Resource r1, Resource r2, boolean text) throws IOException { | |||
if (r1.equals(r2)) { | |||
return 0; | |||
} | |||
boolean e1 = r1.isExists(); | |||
boolean e2 = r2.isExists(); | |||
if (!(e1 || e2)) { | |||
return 0; | |||
} | |||
if (e1 != e2) { | |||
return e1 ? 1 : -1; | |||
} | |||
boolean d1 = r1.isDirectory(); | |||
boolean d2 = r2.isDirectory(); | |||
if (d1 && d2) { | |||
return 0; | |||
} | |||
if (d1 || d2) { | |||
return d1 ? -1 : 1; | |||
} | |||
return text ? textCompare(r1, r2) : binaryCompare(r1, r2); | |||
} | |||
/** | |||
* Binary compares the contents of two Resources. | |||
* <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> | |||
* | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
*/ | |||
private int binaryCompare(Resource r1, Resource r2) throws IOException { | |||
InputStream in1 = null; | |||
InputStream in2 = null; | |||
try { | |||
in1 = new BufferedInputStream(r1.getInputStream()); | |||
in2 = new BufferedInputStream(r2.getInputStream()); | |||
for (int b1 = in1.read(); b1 != -1; b1 = in1.read()) { | |||
int b2 = in2.read(); | |||
if (b1 != b2) { | |||
return b1 > b2 ? 1 : -1; | |||
} | |||
} | |||
return in2.read() == -1 ? 0 : -1; | |||
} finally { | |||
close(in1); | |||
close(in2); | |||
} | |||
} | |||
/** | |||
* Text compares the contents of two Resources. | |||
* Ignores different kinds of line endings. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
*/ | |||
private int textCompare(Resource r1, Resource r2) throws IOException { | |||
BufferedReader in1 = null; | |||
BufferedReader in2 = null; | |||
try { | |||
in1 = new BufferedReader(new InputStreamReader(r1.getInputStream())); | |||
in2 = new BufferedReader(new InputStreamReader(r2.getInputStream())); | |||
String expected = in1.readLine(); | |||
while (expected != null) { | |||
String actual = in2.readLine(); | |||
if (!expected.equals(actual)) { | |||
return expected.compareTo(actual); | |||
} | |||
expected = in1.readLine(); | |||
} | |||
return in2.readLine() == null ? 0 : -1; | |||
} finally { | |||
close(in1); | |||
close(in2); | |||
} | |||
return ResourceUtils.contentEquals( | |||
new FileResource(f1), new FileResource(f2), textfile); | |||
} | |||
/** | |||
@@ -17,18 +17,31 @@ | |||
package org.apache.tools.ant.util; | |||
import java.io.File; | |||
import java.io.Reader; | |||
import java.io.InputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.BufferedReader; | |||
import java.io.BufferedWriter; | |||
import java.io.InputStreamReader; | |||
import java.io.OutputStreamWriter; | |||
import java.io.BufferedInputStream; | |||
import java.util.Arrays; | |||
import java.util.Vector; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.ProjectComponent; | |||
import org.apache.tools.ant.filters.util.ChainReaderHelper; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.TimeComparison; | |||
import org.apache.tools.ant.types.ResourceFactory; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.FilterSetCollection; | |||
import org.apache.tools.ant.types.resources.Union; | |||
import org.apache.tools.ant.types.resources.Restrict; | |||
import org.apache.tools.ant.types.resources.Resources; | |||
import org.apache.tools.ant.types.resources.Touchable; | |||
import org.apache.tools.ant.types.resources.selectors.Or; | |||
import org.apache.tools.ant.types.resources.selectors.And; | |||
import org.apache.tools.ant.types.resources.selectors.Not; | |||
@@ -175,6 +188,360 @@ public class ResourceUtils { | |||
return result; | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another. | |||
* No filtering is performed. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public static void copyResource(Resource source, Resource dest) throws IOException { | |||
copyResource(source, dest, null); | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another. | |||
* No filtering is performed. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public static void copyResource(Resource source, Resource dest, Project project) | |||
throws IOException { | |||
copyResource(source, dest, null, null, false, | |||
false, null, null, project); | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another | |||
* specifying whether token filtering must be used, whether filter chains | |||
* must be used, whether newer destination files may be overwritten and | |||
* whether the last modified time of <code>dest</code> file should be made | |||
* equal to the last modified time of <code>source</code>. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param filters the collection of filters to apply to this copy. | |||
* @param filterChains filterChains to apply during the copy. | |||
* @param overwrite Whether or not the destination Resource should be | |||
* overwritten if it already exists. | |||
* @param preserveLastModified Whether or not the last modified time of | |||
* the destination Resource should be set to that | |||
* of the source. | |||
* @param inputEncoding the encoding used to read the files. | |||
* @param outputEncoding the encoding used to write the files. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public static void copyResource(Resource source, Resource dest, | |||
FilterSetCollection filters, Vector filterChains, | |||
boolean overwrite, boolean preserveLastModified, | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
if (!overwrite) { | |||
long slm = source.getLastModified(); | |||
if (dest.isExists() && slm != 0 | |||
&& dest.getLastModified() > slm) { | |||
return; | |||
} | |||
} | |||
final boolean filterSetsAvailable = (filters != null | |||
&& filters.hasFilters()); | |||
final boolean filterChainsAvailable = (filterChains != null | |||
&& filterChains.size() > 0); | |||
if (filterSetsAvailable) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
InputStreamReader isr = null; | |||
if (inputEncoding == null) { | |||
isr = new InputStreamReader(source.getInputStream()); | |||
} else { | |||
isr = new InputStreamReader(source.getInputStream(), | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(FileUtils.BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
LineTokenizer lineTokenizer = new LineTokenizer(); | |||
lineTokenizer.setIncludeDelims(true); | |||
String newline = null; | |||
String line = lineTokenizer.getToken(in); | |||
while (line != null) { | |||
if (line.length() == 0) { | |||
// this should not happen, because the lines are | |||
// returned with the end of line delimiter | |||
out.newLine(); | |||
} else { | |||
newline = filters.replaceTokens(line); | |||
out.write(newline); | |||
} | |||
line = lineTokenizer.getToken(in); | |||
} | |||
} finally { | |||
FileUtils.close(out); | |||
FileUtils.close(in); | |||
} | |||
} else if (filterChainsAvailable | |||
|| (inputEncoding != null | |||
&& !inputEncoding.equals(outputEncoding)) | |||
|| (inputEncoding == null && outputEncoding != null)) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
InputStreamReader isr = null; | |||
if (inputEncoding == null) { | |||
isr = new InputStreamReader(source.getInputStream()); | |||
} else { | |||
isr = new InputStreamReader(source.getInputStream(), | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(FileUtils.BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
char[] buffer = new char[FileUtils.BUF_SIZE]; | |||
while (true) { | |||
int nRead = in.read(buffer, 0, buffer.length); | |||
if (nRead == -1) { | |||
break; | |||
} | |||
out.write(buffer, 0, nRead); | |||
} | |||
} finally { | |||
FileUtils.close(out); | |||
FileUtils.close(in); | |||
} | |||
} else { | |||
InputStream in = null; | |||
OutputStream out = null; | |||
try { | |||
in = source.getInputStream(); | |||
out = dest.getOutputStream(); | |||
byte[] buffer = new byte[FileUtils.BUF_SIZE]; | |||
int count = 0; | |||
do { | |||
out.write(buffer, 0, count); | |||
count = in.read(buffer, 0, buffer.length); | |||
} while (count != -1); | |||
} finally { | |||
FileUtils.close(out); | |||
FileUtils.close(in); | |||
} | |||
} | |||
if (preserveLastModified && dest instanceof Touchable) { | |||
setLastModified((Touchable) dest, source.getLastModified()); | |||
} | |||
} | |||
/** | |||
* Set the last modified time of an object implementing | |||
* org.apache.tools.ant.types.resources.Touchable . | |||
* | |||
* @param t the Touchable whose modified time is to be set. | |||
* @param time the time to which the last modified time is to be set. | |||
* if this is -1, the current time is used. | |||
* @since Ant 1.7 | |||
*/ | |||
public static void setLastModified(Touchable t, long time) { | |||
t.touch((time < 0) ? System.currentTimeMillis() : time); | |||
} | |||
/** | |||
* Compares the contents of two Resources. | |||
* | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @param text true if the content is to be treated as text and | |||
* differences in kind of line break are to be ignored. | |||
* | |||
* @return true if the content of the Resources is the same. | |||
* | |||
* @throws IOException if the Resources cannot be read. | |||
* @since Ant 1.7 | |||
*/ | |||
public static boolean contentEquals(Resource r1, Resource r2, boolean text) throws IOException { | |||
if (r1.isExists() != r2.isExists()) { | |||
return false; | |||
} | |||
if (!r1.isExists()) { | |||
// two not existing files are equal | |||
return true; | |||
} | |||
// should the following two be switched? If r1 and r2 refer to the same file, | |||
// isn't their content equal regardless of whether that file is a directory? | |||
if (r1.isDirectory() || r2.isDirectory()) { | |||
// don't want to compare directory contents for now | |||
return false; | |||
} | |||
if (r1.equals(r2)) { | |||
return true; | |||
} | |||
if (!text && r1.getSize() != r2.getSize()) { | |||
return false; | |||
} | |||
return compareContent(r1, r2, text) == 0; | |||
} | |||
/** | |||
* Compare the content of two Resources. A nonexistent Resource's | |||
* content is "less than" that of an existing Resource; a directory-type | |||
* Resource's content is "less than" that of a file-type Resource. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @param text true if the content is to be treated as text and | |||
* differences in kind of line break are to be ignored. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
* @since Ant 1.7 | |||
*/ | |||
public static int compareContent(Resource r1, Resource r2, boolean text) throws IOException { | |||
if (r1.equals(r2)) { | |||
return 0; | |||
} | |||
boolean e1 = r1.isExists(); | |||
boolean e2 = r2.isExists(); | |||
if (!(e1 || e2)) { | |||
return 0; | |||
} | |||
if (e1 != e2) { | |||
return e1 ? 1 : -1; | |||
} | |||
boolean d1 = r1.isDirectory(); | |||
boolean d2 = r2.isDirectory(); | |||
if (d1 && d2) { | |||
return 0; | |||
} | |||
if (d1 || d2) { | |||
return d1 ? -1 : 1; | |||
} | |||
return text ? textCompare(r1, r2) : binaryCompare(r1, r2); | |||
} | |||
/** | |||
* Binary compares the contents of two Resources. | |||
* <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> | |||
* | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
* @since Ant 1.7 | |||
*/ | |||
private static int binaryCompare(Resource r1, Resource r2) throws IOException { | |||
InputStream in1 = null; | |||
InputStream in2 = null; | |||
try { | |||
in1 = new BufferedInputStream(r1.getInputStream()); | |||
in2 = new BufferedInputStream(r2.getInputStream()); | |||
for (int b1 = in1.read(); b1 != -1; b1 = in1.read()) { | |||
int b2 = in2.read(); | |||
if (b1 != b2) { | |||
return b1 > b2 ? 1 : -1; | |||
} | |||
} | |||
return in2.read() == -1 ? 0 : -1; | |||
} finally { | |||
FileUtils.close(in1); | |||
FileUtils.close(in2); | |||
} | |||
} | |||
/** | |||
* Text compares the contents of two Resources. | |||
* Ignores different kinds of line endings. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
* @since Ant 1.7 | |||
*/ | |||
private static int textCompare(Resource r1, Resource r2) throws IOException { | |||
BufferedReader in1 = null; | |||
BufferedReader in2 = null; | |||
try { | |||
in1 = new BufferedReader(new InputStreamReader(r1.getInputStream())); | |||
in2 = new BufferedReader(new InputStreamReader(r2.getInputStream())); | |||
String expected = in1.readLine(); | |||
while (expected != null) { | |||
String actual = in2.readLine(); | |||
if (!expected.equals(actual)) { | |||
return expected.compareTo(actual); | |||
} | |||
expected = in1.readLine(); | |||
} | |||
return in2.readLine() == null ? 0 : -1; | |||
} finally { | |||
FileUtils.close(in1); | |||
FileUtils.close(in2); | |||
} | |||
} | |||
/** | |||
* Log which Resources (if any) have been modified in the future. | |||
* @param logTo the ProjectComponent to do the logging. | |||
* @param rc the collection of Resources to check. | |||
* @param long the timestamp granularity to use. | |||
* @since Ant 1.7 | |||
*/ | |||
private static void logFuture(ProjectComponent logTo, | |||
ResourceCollection rc, long granularity) { | |||
long now = System.currentTimeMillis() + granularity; | |||
@@ -34,6 +34,7 @@ import org.apache.tools.ant.types.resources.StringResource; | |||
import org.apache.tools.ant.types.resources.PropertyResource; | |||
import org.apache.tools.ant.types.resources.ImmutableResourceException; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.ResourceUtils; | |||
public class ResourceOutputTest extends BuildFileTest { | |||
@@ -147,7 +148,7 @@ public class ResourceOutputTest extends BuildFileTest { | |||
} | |||
private void testoutput(Resource dest) throws IOException { | |||
FILE_UTILS.copyResource(new StringResource("foo"), dest, null); | |||
ResourceUtils.copyResource(new StringResource("foo"), dest, null); | |||
} | |||
} |