001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.types.selectors;
020:
021: import java.io.File;
022:
023: import org.apache.tools.ant.BuildException;
024: import org.apache.tools.ant.types.EnumeratedAttribute;
025: import org.apache.tools.ant.types.Mapper;
026: import org.apache.tools.ant.util.FileNameMapper;
027: import org.apache.tools.ant.util.IdentityMapper;
028:
029: /**
030: * Selector that filters files based on whether they appear in another
031: * directory tree. It can contain a mapper element, so isn't available
032: * as an ExtendSelector (since those parameters can't hold other
033: * elements).
034: *
035: * @since 1.5
036: */
037: public class PresentSelector extends BaseSelector {
038:
039: private File targetdir = null;
040: private Mapper mapperElement = null;
041: private FileNameMapper map = null;
042: private boolean destmustexist = true;
043:
044: /**
045: * Creates a new <code>PresentSelector</code> instance.
046: *
047: */
048: public PresentSelector() {
049: }
050:
051: /**
052: * @return a string describing this object
053: */
054: public String toString() {
055: StringBuffer buf = new StringBuffer(
056: "{presentselector targetdir: ");
057: if (targetdir == null) {
058: buf.append("NOT YET SET");
059: } else {
060: buf.append(targetdir.getName());
061: }
062: buf.append(" present: ");
063: if (destmustexist) {
064: buf.append("both");
065: } else {
066: buf.append("srconly");
067: }
068: if (map != null) {
069: buf.append(map.toString());
070: } else if (mapperElement != null) {
071: buf.append(mapperElement.toString());
072: }
073: buf.append("}");
074: return buf.toString();
075: }
076:
077: /**
078: * The name of the file or directory which is checked for matching
079: * files.
080: *
081: * @param targetdir the directory to scan looking for matching files.
082: */
083: public void setTargetdir(File targetdir) {
084: this .targetdir = targetdir;
085: }
086:
087: /**
088: * Defines the FileNameMapper to use (nested mapper element).
089: * @return a mapper to be configured
090: * @throws BuildException if more that one mapper defined
091: */
092: public Mapper createMapper() throws BuildException {
093: if (mapperElement != null) {
094: throw new BuildException(
095: "Cannot define more than one mapper");
096: }
097: mapperElement = new Mapper(getProject());
098: return mapperElement;
099: }
100:
101: /**
102: * This sets whether to select a file if its dest file is present.
103: * It could be a <code>negate</code> boolean, but by doing things
104: * this way, we get some documentation on how the system works.
105: * A user looking at the documentation should clearly understand
106: * that the ONLY files whose presence is being tested are those
107: * that already exist in the source directory, hence the lack of
108: * a <code>destonly</code> option.
109: *
110: * @param fp An attribute set to either <code>srconly</code or
111: * <code>both</code>.
112: */
113: public void setPresent(FilePresence fp) {
114: if (fp.getIndex() == 0) {
115: destmustexist = false;
116: }
117: }
118:
119: /**
120: * Checks to make sure all settings are kosher. In this case, it
121: * means that the targetdir attribute has been set and we have a mapper.
122: */
123: public void verifySettings() {
124: if (targetdir == null) {
125: setError("The targetdir attribute is required.");
126: }
127: if (mapperElement == null) {
128: map = new IdentityMapper();
129: } else {
130: map = mapperElement.getImplementation();
131: }
132: if (map == null) {
133: setError("Could not set <mapper> element.");
134: }
135: }
136:
137: /**
138: * The heart of the matter. This is where the selector gets to decide
139: * on the inclusion of a file in a particular fileset.
140: *
141: * @param basedir the base directory the scan is being done from
142: * @param filename is the name of the file to check
143: * @param file is a java.io.File object the selector can use
144: * @return whether the file should be selected or not
145: */
146: public boolean isSelected(File basedir, String filename, File file) {
147:
148: // throw BuildException on error
149: validate();
150:
151: // Determine file whose existence is to be checked
152: String[] destfiles = map.mapFileName(filename);
153: // If filename does not match the To attribute of the mapper
154: // then filter it out of the files we are considering
155: if (destfiles == null) {
156: return false;
157: }
158: // Sanity check
159: if (destfiles.length != 1 || destfiles[0] == null) {
160: throw new BuildException(
161: "Invalid destination file results for " + targetdir
162: + " with filename " + filename);
163: }
164: String destname = destfiles[0];
165: File destfile = new File(targetdir, destname);
166: return destfile.exists() == destmustexist;
167: }
168:
169: /**
170: * Enumerated attribute with the values for indicating where a file's
171: * presence is allowed and required.
172: */
173: public static class FilePresence extends EnumeratedAttribute {
174: /**
175: * @return the values as an array of strings
176: */
177: public String[] getValues() {
178: return new String[] { "srconly", "both" };
179: }
180: }
181:
182: }
|