1. /*
  2. * Copyright 2000-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.types.selectors;
  18. import org.apache.tools.ant.util.FileUtils;
  19. import org.apache.tools.ant.BuildException;
  20. import java.io.File;
  21. import java.io.IOException;
  22. /**
  23. * This selector selects files against a mapped set of target files, selecting
  24. * all those files which are different. A byte-by-byte comparision is performed
  25. * on equal length files; files with different lengths are deemed different
  26. * automatically; files with identical timestamps are viewed as matching by
  27. * default, unless you specify otherwise.
  28. * <p>
  29. * This is a useful selector to work with programs and tasks that don't handle
  30. * dependency checking properly; Even if a predecessor task always creates its
  31. * output files, followup tasks can be driven off copies made with a different
  32. * selector, so their dependencies are driven on the absolute state of the
  33. * files, not a timestamp.
  34. * <p>
  35. * Clearly, however, bulk file comparisons is inefficient; anything that can
  36. * use timestamps is to be preferred. If this selector must be used, use it
  37. * over as few files as possible, perhaps following it with an <uptodate;>
  38. * to keep the descendent routines conditional.
  39. *
  40. */
  41. public class DifferentSelector extends MappingSelector {
  42. private FileUtils fileUtils = FileUtils.newFileUtils();
  43. private boolean ignoreFileTimes = true;
  44. /**
  45. * This flag tells the selector to ignore file times in the comparison
  46. * @param ignoreFileTimes if true ignore file times
  47. */
  48. public void setIgnoreFileTimes(boolean ignoreFileTimes) {
  49. this.ignoreFileTimes = ignoreFileTimes;
  50. }
  51. /**
  52. * this test is our selection test that compared the file with the destfile
  53. * @param srcfile the source file
  54. * @param destfile the destination file
  55. * @return true if the files are different
  56. */
  57. protected boolean selectionTest(File srcfile, File destfile) {
  58. //if either of them is missing, they are different
  59. if (srcfile.exists() != destfile.exists()) {
  60. return true;
  61. }
  62. if (srcfile.length() != destfile.length()) {
  63. // different size =>different files
  64. return true;
  65. }
  66. if (!ignoreFileTimes) {
  67. //same date if dest timestamp is within granularity of the srcfile
  68. boolean sameDate;
  69. sameDate = destfile.lastModified() >= srcfile.lastModified() - granularity
  70. && destfile.lastModified() <= srcfile.lastModified() + granularity;
  71. // different dates => different files
  72. if (!sameDate) {
  73. return true;
  74. }
  75. }
  76. //here do a bulk comparison
  77. try {
  78. return !fileUtils.contentEquals(srcfile, destfile);
  79. } catch (IOException e) {
  80. throw new BuildException("while comparing " + srcfile + " and "
  81. + destfile, e);
  82. }
  83. }
  84. }