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); | |||
| } | |||
| } | |||