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;
  18. import java.util.Properties;
  19. import java.util.Stack;
  20. import org.apache.tools.ant.AntClassLoader;
  21. import org.apache.tools.ant.BuildException;
  22. import org.apache.tools.ant.Project;
  23. import org.apache.tools.ant.util.FileNameMapper;
  24. import org.apache.tools.ant.util.CompositeMapper;
  25. import org.apache.tools.ant.util.ContainerMapper;
  26. /**
  27. * Element to define a FileNameMapper.
  28. *
  29. */
  30. public class Mapper extends DataType implements Cloneable {
  31. protected MapperType type = null;
  32. protected String classname = null;
  33. protected Path classpath = null;
  34. protected String from = null;
  35. protected String to = null;
  36. private ContainerMapper container = null;
  37. /**
  38. * Construct a new <CODE>Mapper</CODE> element.
  39. * @param p the owning Ant <CODE>Project</CODE>.
  40. */
  41. public Mapper(Project p) {
  42. setProject(p);
  43. }
  44. /**
  45. * Set the type of <code>FileNameMapper</code> to use.
  46. * @param type the <CODE>MapperType</CODE> enumerated attribute.
  47. */
  48. public void setType(MapperType type) {
  49. if (isReference()) {
  50. throw tooManyAttributes();
  51. }
  52. this.type = type;
  53. }
  54. /**
  55. * Add a nested <CODE>FileNameMapper</CODE>.
  56. * @param fileNameMapper the <CODE>FileNameMapper</CODE> to add.
  57. */
  58. public void add(FileNameMapper fileNameMapper) {
  59. if (isReference()) {
  60. throw noChildrenAllowed();
  61. }
  62. if (container == null) {
  63. if (type == null && classname == null) {
  64. container = new CompositeMapper();
  65. } else {
  66. FileNameMapper m = getImplementation();
  67. if (m instanceof ContainerMapper) {
  68. container = (ContainerMapper)m;
  69. } else {
  70. throw new BuildException(String.valueOf(m)
  71. + " mapper implementation does not support nested mappers!");
  72. }
  73. }
  74. }
  75. container.add(fileNameMapper);
  76. }
  77. /**
  78. * Add a Mapper
  79. * @param mapper the mapper to add
  80. */
  81. public void addConfiguredMapper(Mapper mapper) {
  82. add(mapper.getImplementation());
  83. }
  84. /**
  85. * Set the class name of the FileNameMapper to use.
  86. */
  87. public void setClassname(String classname) {
  88. if (isReference()) {
  89. throw tooManyAttributes();
  90. }
  91. this.classname = classname;
  92. }
  93. /**
  94. * Set the classpath to load the FileNameMapper through (attribute).
  95. */
  96. public void setClasspath(Path classpath) {
  97. if (isReference()) {
  98. throw tooManyAttributes();
  99. }
  100. if (this.classpath == null) {
  101. this.classpath = classpath;
  102. } else {
  103. this.classpath.append(classpath);
  104. }
  105. }
  106. /**
  107. * Set the classpath to load the FileNameMapper through (nested element).
  108. */
  109. public Path createClasspath() {
  110. if (isReference()) {
  111. throw noChildrenAllowed();
  112. }
  113. if (this.classpath == null) {
  114. this.classpath = new Path(getProject());
  115. }
  116. return this.classpath.createPath();
  117. }
  118. /**
  119. * Set the classpath to load the FileNameMapper through via
  120. * reference (attribute).
  121. */
  122. public void setClasspathRef(Reference r) {
  123. if (isReference()) {
  124. throw tooManyAttributes();
  125. }
  126. createClasspath().setRefid(r);
  127. }
  128. /**
  129. * Set the argument to FileNameMapper.setFrom
  130. */
  131. public void setFrom(String from) {
  132. if (isReference()) {
  133. throw tooManyAttributes();
  134. }
  135. this.from = from;
  136. }
  137. /**
  138. * Set the argument to FileNameMapper.setTo
  139. */
  140. public void setTo(String to) {
  141. if (isReference()) {
  142. throw tooManyAttributes();
  143. }
  144. this.to = to;
  145. }
  146. /**
  147. * Make this Mapper instance a reference to another Mapper.
  148. *
  149. * <p>You must not set any other attribute if you make it a
  150. * reference.</p>
  151. */
  152. public void setRefid(Reference r) throws BuildException {
  153. if (type != null || from != null || to != null) {
  154. throw tooManyAttributes();
  155. }
  156. super.setRefid(r);
  157. }
  158. /**
  159. * Returns a fully configured FileNameMapper implementation.
  160. */
  161. public FileNameMapper getImplementation() throws BuildException {
  162. if (isReference()) {
  163. return getRef().getImplementation();
  164. }
  165. if (type == null && classname == null && container == null) {
  166. throw new BuildException(
  167. "nested mapper or "
  168. + "one of the attributes type or classname is required");
  169. }
  170. if (container != null) {
  171. return container;
  172. }
  173. if (type != null && classname != null) {
  174. throw new BuildException(
  175. "must not specify both type and classname attribute");
  176. }
  177. try {
  178. FileNameMapper m
  179. = (FileNameMapper)(getImplementationClass().newInstance());
  180. final Project project = getProject();
  181. if (project != null) {
  182. project.setProjectReference(m);
  183. }
  184. m.setFrom(from);
  185. m.setTo(to);
  186. return m;
  187. } catch (BuildException be) {
  188. throw be;
  189. } catch (Throwable t) {
  190. throw new BuildException(t);
  191. }
  192. }
  193. /**
  194. * Gets the Class object associated with the mapper implementation.
  195. * @return <CODE>Class</CODE>.
  196. */
  197. protected Class getImplementationClass() throws ClassNotFoundException {
  198. String classname = this.classname;
  199. if (type != null) {
  200. classname = type.getImplementation();
  201. }
  202. ClassLoader loader = (classpath == null)
  203. ? getClass().getClassLoader()
  204. : getProject().createClassLoader(classpath);
  205. return Class.forName(classname, true, loader);
  206. }
  207. /**
  208. * Performs the check for circular references and returns the
  209. * referenced Mapper.
  210. */
  211. protected Mapper getRef() {
  212. if (!isChecked()) {
  213. Stack stk = new Stack();
  214. stk.push(this);
  215. dieOnCircularReference(stk, getProject());
  216. }
  217. Object o = getRefid().getReferencedObject(getProject());
  218. if (!(o instanceof Mapper)) {
  219. String msg = getRefid().getRefId() + " doesn\'t denote a mapper";
  220. throw new BuildException(msg);
  221. } else {
  222. return (Mapper) o;
  223. }
  224. }
  225. /**
  226. * Class as Argument to FileNameMapper.setType.
  227. */
  228. public static class MapperType extends EnumeratedAttribute {
  229. private Properties implementations;
  230. public MapperType() {
  231. implementations = new Properties();
  232. implementations.put("identity",
  233. "org.apache.tools.ant.util.IdentityMapper");
  234. implementations.put("flatten",
  235. "org.apache.tools.ant.util.FlatFileNameMapper");
  236. implementations.put("glob",
  237. "org.apache.tools.ant.util.GlobPatternMapper");
  238. implementations.put("merge",
  239. "org.apache.tools.ant.util.MergingMapper");
  240. implementations.put("regexp",
  241. "org.apache.tools.ant.util.RegexpPatternMapper");
  242. implementations.put("package",
  243. "org.apache.tools.ant.util.PackageNameMapper");
  244. implementations.put("unpackage",
  245. "org.apache.tools.ant.util.UnPackageNameMapper");
  246. }
  247. public String[] getValues() {
  248. return new String[] {"identity", "flatten", "glob",
  249. "merge", "regexp", "package", "unpackage"};
  250. }
  251. public String getImplementation() {
  252. return implementations.getProperty(getValue());
  253. }
  254. }
  255. }