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.BuildException; | ||||
| import org.apache.tools.ant.types.Resource; | 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. | * Compares Resources by content. | ||||
| @@ -60,7 +60,7 @@ public class Content extends ResourceComparator { | |||||
| */ | */ | ||||
| protected int resourceCompare(Resource foo, Resource bar) { | protected int resourceCompare(Resource foo, Resource bar) { | ||||
| try { | try { | ||||
| return FileUtils.getFileUtils().compareContent(foo, bar, !binary); | |||||
| return ResourceUtils.compareContent(foo, bar, !binary); | |||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| throw new BuildException(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.resources.selectors.ResourceSelector; | ||||
| import org.apache.tools.ant.types.selectors.BaseExtendSelector; | import org.apache.tools.ant.types.selectors.BaseExtendSelector; | ||||
| import org.apache.tools.ant.util.FileUtils; | 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(); | FileUtils fu = FileUtils.getFileUtils(); | ||||
| File tmpFile = fu.createTempFile("modified-", ".tmp", null); | File tmpFile = fu.createTempFile("modified-", ".tmp", null); | ||||
| Resource tmpResource = new FileResource(tmpFile); | Resource tmpResource = new FileResource(tmpFile); | ||||
| fu.copyResource(resource, tmpResource); | |||||
| ResourceUtils.copyResource(resource, tmpResource); | |||||
| boolean isSelected = isSelected(tmpFile.getParentFile(), | boolean isSelected = isSelected(tmpFile.getParentFile(), | ||||
| tmpFile.getName(), | tmpFile.getName(), | ||||
| resource.toLongString()); | resource.toLongString()); | ||||
| @@ -41,9 +41,7 @@ import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.filters.util.ChainReaderHelper; | import org.apache.tools.ant.filters.util.ChainReaderHelper; | ||||
| import org.apache.tools.ant.taskdefs.condition.Os; | 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.FilterSetCollection; | ||||
| import org.apache.tools.ant.types.resources.Touchable; | |||||
| import org.apache.tools.ant.types.resources.FileResource; | import org.apache.tools.ant.types.resources.FileResource; | ||||
| import org.apache.tools.ant.launch.Locator; | import org.apache.tools.ant.launch.Locator; | ||||
| @@ -54,7 +52,6 @@ import org.apache.tools.ant.launch.Locator; | |||||
| * their last modification time. | * their last modification time. | ||||
| * | * | ||||
| */ | */ | ||||
| public class FileUtils { | public class FileUtils { | ||||
| private static final FileUtils PRIMARY_INSTANCE = new 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 onWin9x = Os.isFamily("win9x"); | ||||
| private static boolean onWindows = Os.isFamily("windows"); | private static boolean onWindows = Os.isFamily("windows"); | ||||
| private static final int BUF_SIZE = 8192; | |||||
| static final int BUF_SIZE = 8192; | |||||
| // for toURI | // for toURI | ||||
| private static boolean[] isSpecial = new boolean[256]; | private static boolean[] isSpecial = new boolean[256]; | ||||
| @@ -520,206 +517,12 @@ public class FileUtils { | |||||
| String inputEncoding, String outputEncoding, | String inputEncoding, String outputEncoding, | ||||
| Project project) | Project project) | ||||
| throws IOException { | throws IOException { | ||||
| copyResource(new FileResource(sourceFile), new FileResource(destFile), | |||||
| ResourceUtils.copyResource( | |||||
| new FileResource(sourceFile), new FileResource(destFile), | |||||
| filters, filterChains, overwrite, preserveLastModified, | filters, filterChains, overwrite, preserveLastModified, | ||||
| inputEncoding, outputEncoding, project); | 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 | * Calls File.setLastModified(long time). Originally written to | ||||
| * to dynamically bind to that call on Java1.2+. | * 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. | * if this is -1, the current time is used. | ||||
| */ | */ | ||||
| public void setFileLastModified(File file, long time) { | 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. | * @param path the path to dissect. | ||||
| * @return String[] {root, remaining path}. | * @return String[] {root, remaining path}. | ||||
| * @throws java.lang.NullPointerException if path is null. | * @throws java.lang.NullPointerException if path is null. | ||||
| * @since Ant 1.7 | |||||
| */ | */ | ||||
| public String[] dissect(String path) { | public String[] dissect(String path) { | ||||
| char sep = File.separatorChar; | char sep = File.separatorChar; | ||||
| @@ -1063,143 +855,8 @@ public class FileUtils { | |||||
| * @since Ant 1.6.3 | * @since Ant 1.6.3 | ||||
| */ | */ | ||||
| public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { | 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; | package org.apache.tools.ant.util; | ||||
| import java.io.File; | 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.Arrays; | ||||
| import java.util.Vector; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.ProjectComponent; | 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.Resource; | ||||
| import org.apache.tools.ant.types.TimeComparison; | import org.apache.tools.ant.types.TimeComparison; | ||||
| import org.apache.tools.ant.types.ResourceFactory; | import org.apache.tools.ant.types.ResourceFactory; | ||||
| import org.apache.tools.ant.types.ResourceCollection; | 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.Union; | ||||
| import org.apache.tools.ant.types.resources.Restrict; | import org.apache.tools.ant.types.resources.Restrict; | ||||
| import org.apache.tools.ant.types.resources.Resources; | 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.Or; | ||||
| import org.apache.tools.ant.types.resources.selectors.And; | import org.apache.tools.ant.types.resources.selectors.And; | ||||
| import org.apache.tools.ant.types.resources.selectors.Not; | import org.apache.tools.ant.types.resources.selectors.Not; | ||||
| @@ -175,6 +188,360 @@ public class ResourceUtils { | |||||
| return result; | 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, | private static void logFuture(ProjectComponent logTo, | ||||
| ResourceCollection rc, long granularity) { | ResourceCollection rc, long granularity) { | ||||
| long now = System.currentTimeMillis() + 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.PropertyResource; | ||||
| import org.apache.tools.ant.types.resources.ImmutableResourceException; | import org.apache.tools.ant.types.resources.ImmutableResourceException; | ||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import org.apache.tools.ant.util.ResourceUtils; | |||||
| public class ResourceOutputTest extends BuildFileTest { | public class ResourceOutputTest extends BuildFileTest { | ||||
| @@ -147,7 +148,7 @@ public class ResourceOutputTest extends BuildFileTest { | |||||
| } | } | ||||
| private void testoutput(Resource dest) throws IOException { | private void testoutput(Resource dest) throws IOException { | ||||
| FILE_UTILS.copyResource(new StringResource("foo"), dest, null); | |||||
| ResourceUtils.copyResource(new StringResource("foo"), dest, null); | |||||
| } | } | ||||
| } | } | ||||