From fa84f9f4612033d0b9d171822cc9af6593602f8e Mon Sep 17 00:00:00 2001 From: Matthew Jason Benson Date: Thu, 29 Sep 2005 21:09:44 +0000 Subject: [PATCH] Move Resource-based utility methods in FileUtils to ResourceUtils (static). git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@292553 13f79535-47bb-0310-9956-ffa450edef68 --- .../types/resources/comparators/Content.java | 4 +- .../modifiedselector/ModifiedSelector.java | 3 +- .../org/apache/tools/ant/util/FileUtils.java | 357 +---------------- .../apache/tools/ant/util/ResourceUtils.java | 367 ++++++++++++++++++ .../tools/ant/types/ResourceOutputTest.java | 3 +- 5 files changed, 380 insertions(+), 354 deletions(-) diff --git a/src/main/org/apache/tools/ant/types/resources/comparators/Content.java b/src/main/org/apache/tools/ant/types/resources/comparators/Content.java index d212cf037..9b2db8d11 100755 --- a/src/main/org/apache/tools/ant/types/resources/comparators/Content.java +++ b/src/main/org/apache/tools/ant/types/resources/comparators/Content.java @@ -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); } diff --git a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java index 89bffe2ef..83e719279 100644 --- a/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java +++ b/src/main/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java @@ -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()); diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index 2d9846c39..aa71197ec 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -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 null. - * @param dest the Resource to copy to. - * Must not be null. - * - * @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 null. - * @param dest the Resource to copy to. - * Must not be null. - * @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 dest file should be made - * equal to the last modified time of source. - * - * @param source the Resource to copy from. - * Must not be null. - * @param dest the Resource to copy to. - * Must not be null. - * @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. - *

- * 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. - *

- * - * @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); } /** diff --git a/src/main/org/apache/tools/ant/util/ResourceUtils.java b/src/main/org/apache/tools/ant/util/ResourceUtils.java index ff79f2bd4..ce3ff8ace 100644 --- a/src/main/org/apache/tools/ant/util/ResourceUtils.java +++ b/src/main/org/apache/tools/ant/util/ResourceUtils.java @@ -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 null. + * @param dest the Resource to copy to. + * Must not be null. + * + * @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 null. + * @param dest the Resource to copy to. + * Must not be null. + * @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 dest file should be made + * equal to the last modified time of source. + * + * @param source the Resource to copy from. + * Must not be null. + * @param dest the Resource to copy to. + * Must not be null. + * @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. + *

+ * 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. + *

+ * + * @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; diff --git a/src/testcases/org/apache/tools/ant/types/ResourceOutputTest.java b/src/testcases/org/apache/tools/ant/types/ResourceOutputTest.java index 9ac58c30f..4c20b5121 100755 --- a/src/testcases/org/apache/tools/ant/types/ResourceOutputTest.java +++ b/src/testcases/org/apache/tools/ant/types/ResourceOutputTest.java @@ -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); } }