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;
020:
021: import java.util.Properties;
022: import org.apache.tools.ant.BuildException;
023: import org.apache.tools.ant.Project;
024: import org.apache.tools.ant.util.FileNameMapper;
025: import org.apache.tools.ant.util.CompositeMapper;
026: import org.apache.tools.ant.util.ContainerMapper;
027:
028: /**
029: * Element to define a FileNameMapper.
030: *
031: */
032: public class Mapper extends DataType implements Cloneable {
033: // CheckStyle:VisibilityModifier OFF - bc
034:
035: protected MapperType type = null;
036: protected String classname = null;
037: protected Path classpath = null;
038: protected String from = null;
039: protected String to = null;
040:
041: // CheckStyle:VisibilityModifier ON
042:
043: private ContainerMapper container = null;
044:
045: /**
046: * Construct a new <code>Mapper</code> element.
047: * @param p the owning Ant <code>Project</code>.
048: */
049: public Mapper(Project p) {
050: setProject(p);
051: }
052:
053: /**
054: * Set the type of <code>FileNameMapper</code> to use.
055: * @param type the <code>MapperType</code> enumerated attribute.
056: */
057: public void setType(MapperType type) {
058: if (isReference()) {
059: throw tooManyAttributes();
060: }
061: this .type = type;
062: }
063:
064: /**
065: * Cannot mix add and addconfigured in same type, so
066: * provide this to override the add method.
067: * @param fileNameMapper the <code>FileNameMapper</code> to add.
068: */
069: public void addConfigured(FileNameMapper fileNameMapper) {
070: add(fileNameMapper);
071: }
072:
073: /**
074: * Add a nested <code>FileNameMapper</code>.
075: * @param fileNameMapper the <code>FileNameMapper</code> to add.
076: */
077: public void add(FileNameMapper fileNameMapper) {
078: if (isReference()) {
079: throw noChildrenAllowed();
080: }
081: if (container == null) {
082: if (type == null && classname == null) {
083: container = new CompositeMapper();
084: } else {
085: FileNameMapper m = getImplementation();
086: if (m instanceof ContainerMapper) {
087: container = (ContainerMapper) m;
088: } else {
089: throw new BuildException(
090: String.valueOf(m)
091: + " mapper implementation does not support nested mappers!");
092: }
093: }
094: }
095: container.add(fileNameMapper);
096: }
097:
098: /**
099: * Add a Mapper
100: * @param mapper the mapper to add
101: */
102: public void addConfiguredMapper(Mapper mapper) {
103: add(mapper.getImplementation());
104: }
105:
106: /**
107: * Set the class name of the FileNameMapper to use.
108: * @param classname the name of the class
109: */
110: public void setClassname(String classname) {
111: if (isReference()) {
112: throw tooManyAttributes();
113: }
114: this .classname = classname;
115: }
116:
117: /**
118: * Set the classpath to load the FileNameMapper through (attribute).
119: * @param classpath the classpath
120: */
121: public void setClasspath(Path classpath) {
122: if (isReference()) {
123: throw tooManyAttributes();
124: }
125: if (this .classpath == null) {
126: this .classpath = classpath;
127: } else {
128: this .classpath.append(classpath);
129: }
130: }
131:
132: /**
133: * Set the classpath to load the FileNameMapper through (nested element).
134: * @return a path object to be configured
135: */
136: public Path createClasspath() {
137: if (isReference()) {
138: throw noChildrenAllowed();
139: }
140: if (this .classpath == null) {
141: this .classpath = new Path(getProject());
142: }
143: return this .classpath.createPath();
144: }
145:
146: /**
147: * Set the classpath to load the FileNameMapper through via
148: * reference (attribute).
149: * @param ref the reference to the FileNameMapper
150: */
151: public void setClasspathRef(Reference ref) {
152: if (isReference()) {
153: throw tooManyAttributes();
154: }
155: createClasspath().setRefid(ref);
156: }
157:
158: /**
159: * Set the argument to FileNameMapper.setFrom
160: * @param from the from attribute to pass to the FileNameMapper
161: */
162: public void setFrom(String from) {
163: if (isReference()) {
164: throw tooManyAttributes();
165: }
166: this .from = from;
167: }
168:
169: /**
170: * Set the argument to FileNameMapper.setTo
171: * @param to the to attribute to pass to the FileNameMapper
172: */
173: public void setTo(String to) {
174: if (isReference()) {
175: throw tooManyAttributes();
176: }
177: this .to = to;
178: }
179:
180: /**
181: * Make this Mapper instance a reference to another Mapper.
182: *
183: * <p>You must not set any other attribute if you make it a
184: * reference.</p>
185: * @param r the reference to another mapper
186: * @throws BuildException if other attributes are set
187: */
188: public void setRefid(Reference r) throws BuildException {
189: if (type != null || from != null || to != null) {
190: throw tooManyAttributes();
191: }
192: super .setRefid(r);
193: }
194:
195: /**
196: * Returns a fully configured FileNameMapper implementation.
197: * @return a FileNameMapper object to be configured
198: * @throws BuildException on error
199: */
200: public FileNameMapper getImplementation() throws BuildException {
201: if (isReference()) {
202: return getRef().getImplementation();
203: }
204:
205: if (type == null && classname == null && container == null) {
206: throw new BuildException(
207: "nested mapper or "
208: + "one of the attributes type or classname is required");
209: }
210:
211: if (container != null) {
212: return container;
213: }
214:
215: if (type != null && classname != null) {
216: throw new BuildException(
217: "must not specify both type and classname attribute");
218: }
219:
220: try {
221: FileNameMapper m = (FileNameMapper) (getImplementationClass()
222: .newInstance());
223: final Project p = getProject();
224: if (p != null) {
225: p.setProjectReference(m);
226: }
227: m.setFrom(from);
228: m.setTo(to);
229:
230: return m;
231: } catch (BuildException be) {
232: throw be;
233: } catch (Throwable t) {
234: throw new BuildException(t);
235: }
236: }
237:
238: /**
239: * Gets the Class object associated with the mapper implementation.
240: * @return <code>Class</code>.
241: * @throws ClassNotFoundException if the class cannot be found
242: */
243: protected Class getImplementationClass()
244: throws ClassNotFoundException {
245:
246: String cName = this .classname;
247: if (type != null) {
248: cName = type.getImplementation();
249: }
250:
251: ClassLoader loader = (classpath == null) ? getClass()
252: .getClassLoader() : getProject().createClassLoader(
253: classpath);
254:
255: return Class.forName(cName, true, loader);
256: }
257:
258: /**
259: * Performs the check for circular references and returns the
260: * referenced Mapper.
261: * @return the referenced Mapper
262: */
263: protected Mapper getRef() {
264: return (Mapper) getCheckedRef();
265: }
266:
267: /**
268: * Class as Argument to FileNameMapper.setType.
269: */
270: public static class MapperType extends EnumeratedAttribute {
271: private Properties implementations;
272:
273: /** Constructor for the MapperType enumeration */
274: public MapperType() {
275: implementations = new Properties();
276: implementations.put("identity",
277: "org.apache.tools.ant.util.IdentityMapper");
278: implementations.put("flatten",
279: "org.apache.tools.ant.util.FlatFileNameMapper");
280: implementations.put("glob",
281: "org.apache.tools.ant.util.GlobPatternMapper");
282: implementations.put("merge",
283: "org.apache.tools.ant.util.MergingMapper");
284: implementations.put("regexp",
285: "org.apache.tools.ant.util.RegexpPatternMapper");
286: implementations.put("package",
287: "org.apache.tools.ant.util.PackageNameMapper");
288: implementations.put("unpackage",
289: "org.apache.tools.ant.util.UnPackageNameMapper");
290: }
291:
292: /**
293: * @return the filenamemapper names
294: */
295: public String[] getValues() {
296: return new String[] { "identity", "flatten", "glob",
297: "merge", "regexp", "package", "unpackage" };
298: }
299:
300: /**
301: * @return the classname for the filenamemapper name
302: */
303: public String getImplementation() {
304: return implementations.getProperty(getValue());
305: }
306: }
307:
308: }
|