1. /*
  2. * Copyright 2002-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 java.io.File;
  19. import org.apache.tools.ant.BuildException;
  20. import org.apache.tools.ant.types.EnumeratedAttribute;
  21. import org.apache.tools.ant.types.Mapper;
  22. import org.apache.tools.ant.util.FileNameMapper;
  23. import org.apache.tools.ant.util.IdentityMapper;
  24. /**
  25. * Selector that filters files based on whether they appear in another
  26. * directory tree. It can contain a mapper element, so isn't available
  27. * as an ExtendSelector (since those parameters can't hold other
  28. * elements).
  29. *
  30. * @since 1.5
  31. */
  32. public class PresentSelector extends BaseSelector {
  33. private File targetdir = null;
  34. private Mapper mapperElement = null;
  35. private FileNameMapper map = null;
  36. private boolean destmustexist = true;
  37. /**
  38. * Creates a new <code>PresentSelector</code> instance.
  39. *
  40. */
  41. public PresentSelector() {
  42. }
  43. /**
  44. * @return a string describing this object
  45. */
  46. public String toString() {
  47. StringBuffer buf = new StringBuffer("{presentselector targetdir: ");
  48. if (targetdir == null) {
  49. buf.append("NOT YET SET");
  50. } else {
  51. buf.append(targetdir.getName());
  52. }
  53. buf.append(" present: ");
  54. if (destmustexist) {
  55. buf.append("both");
  56. } else {
  57. buf.append("srconly");
  58. }
  59. if (map != null) {
  60. buf.append(map.toString());
  61. } else if (mapperElement != null) {
  62. buf.append(mapperElement.toString());
  63. }
  64. buf.append("}");
  65. return buf.toString();
  66. }
  67. /**
  68. * The name of the file or directory which is checked for matching
  69. * files.
  70. *
  71. * @param targetdir the directory to scan looking for matching files.
  72. */
  73. public void setTargetdir(File targetdir) {
  74. this.targetdir = targetdir;
  75. }
  76. /**
  77. * Defines the FileNameMapper to use (nested mapper element).
  78. * @return a mapper to be configured
  79. * @throws BuildException if more that one mapper defined
  80. */
  81. public Mapper createMapper() throws BuildException {
  82. if (mapperElement != null) {
  83. throw new BuildException("Cannot define more than one mapper");
  84. }
  85. mapperElement = new Mapper(getProject());
  86. return mapperElement;
  87. }
  88. /**
  89. * This sets whether to select a file if its dest file is present.
  90. * It could be a <code>negate</code> boolean, but by doing things
  91. * this way, we get some documentation on how the system works.
  92. * A user looking at the documentation should clearly understand
  93. * that the ONLY files whose presence is being tested are those
  94. * that already exist in the source directory, hence the lack of
  95. * a <code>destonly</code> option.
  96. *
  97. * @param fp An attribute set to either <code>srconly</code or
  98. * <code>both</code>.
  99. */
  100. public void setPresent(FilePresence fp) {
  101. if (fp.getIndex() == 0) {
  102. destmustexist = false;
  103. }
  104. }
  105. /**
  106. * Checks to make sure all settings are kosher. In this case, it
  107. * means that the targetdir attribute has been set and we have a mapper.
  108. */
  109. public void verifySettings() {
  110. if (targetdir == null) {
  111. setError("The targetdir attribute is required.");
  112. }
  113. if (mapperElement == null) {
  114. map = new IdentityMapper();
  115. } else {
  116. map = mapperElement.getImplementation();
  117. }
  118. if (map == null) {
  119. setError("Could not set <mapper> element.");
  120. }
  121. }
  122. /**
  123. * The heart of the matter. This is where the selector gets to decide
  124. * on the inclusion of a file in a particular fileset.
  125. *
  126. * @param basedir the base directory the scan is being done from
  127. * @param filename is the name of the file to check
  128. * @param file is a java.io.File object the selector can use
  129. * @return whether the file should be selected or not
  130. */
  131. public boolean isSelected(File basedir, String filename, File file) {
  132. // throw BuildException on error
  133. validate();
  134. // Determine file whose existence is to be checked
  135. String[] destfiles = map.mapFileName(filename);
  136. // If filename does not match the To attribute of the mapper
  137. // then filter it out of the files we are considering
  138. if (destfiles == null) {
  139. return false;
  140. }
  141. // Sanity check
  142. if (destfiles.length != 1 || destfiles[0] == null) {
  143. throw new BuildException("Invalid destination file results for "
  144. + targetdir + " with filename " + filename);
  145. }
  146. String destname = destfiles[0];
  147. File destfile = new File(targetdir, destname);
  148. return destfile.exists() == destmustexist;
  149. }
  150. /**
  151. * Enumerated attribute with the values for indicating where a file's
  152. * presence is allowed and required.
  153. */
  154. public static class FilePresence extends EnumeratedAttribute {
  155. /**
  156. * @return the values as an array of strings
  157. */
  158. public String[] getValues() {
  159. return new String[]{"srconly", "both"};
  160. }
  161. }
  162. }