1. /*
  2. * Copyright 2003-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.taskdefs;
  18. import org.apache.tools.ant.AntTypeDefinition;
  19. import org.apache.tools.ant.BuildException;
  20. import org.apache.tools.ant.ComponentHelper;
  21. import org.apache.tools.ant.Project;
  22. import org.apache.tools.ant.ProjectHelper;
  23. import org.apache.tools.ant.Task;
  24. import org.apache.tools.ant.TaskContainer;
  25. import org.apache.tools.ant.UnknownElement;
  26. /**
  27. * The preset definition task generates a new definition
  28. * based on a current definition with some attributes or
  29. * elements preset.
  30. * <pre>
  31. * <presetdef name="my.javac">
  32. * <javac deprecation="${deprecation}" debug="${debug}"/>
  33. * </presetdef>
  34. * <my.javac srcdir="src" destdir="classes"/>
  35. * </pre>
  36. *
  37. * @since Ant 1.6
  38. */
  39. public class PreSetDef extends AntlibDefinition implements TaskContainer {
  40. private UnknownElement nestedTask;
  41. private String name;
  42. /**
  43. * Name of the definition
  44. * @param name the name of the definition
  45. */
  46. public void setName(String name) {
  47. this.name = name;
  48. }
  49. /**
  50. * Add a nested task to predefine attributes and elements on
  51. * @param nestedTask Nested task/type to extend
  52. */
  53. public void addTask(Task nestedTask) {
  54. if (this.nestedTask != null) {
  55. throw new BuildException("Only one nested element allowed");
  56. }
  57. if (!(nestedTask instanceof UnknownElement)) {
  58. throw new BuildException(
  59. "addTask called with a task that is not an unknown element");
  60. }
  61. this.nestedTask = (UnknownElement) nestedTask;
  62. }
  63. /**
  64. * make a new definition
  65. */
  66. public void execute() {
  67. if (nestedTask == null) {
  68. throw new BuildException("Missing nested element");
  69. }
  70. if (name == null) {
  71. throw new BuildException("Name not specified");
  72. }
  73. name = ProjectHelper.genComponentName(getURI(), name);
  74. ComponentHelper helper = ComponentHelper.getComponentHelper(
  75. getProject());
  76. String componentName = ProjectHelper.genComponentName(
  77. nestedTask.getNamespace(), nestedTask.getTag());
  78. AntTypeDefinition def = helper.getDefinition(componentName);
  79. if (def == null) {
  80. throw new BuildException(
  81. "Unable to find typedef " + componentName);
  82. }
  83. PreSetDefinition newDef = new PreSetDefinition(def, nestedTask);
  84. newDef.setName(name);
  85. helper.addDataTypeDefinition(newDef);
  86. }
  87. /**
  88. * This class contains the unknown element and the object
  89. * that is predefined.
  90. * @see AntTypeDefinition
  91. */
  92. public static class PreSetDefinition extends AntTypeDefinition {
  93. private AntTypeDefinition parent;
  94. private UnknownElement element;
  95. /**
  96. * Creates a new <code>PresetDefinition</code> instance.
  97. *
  98. * @param parent The parent of this predefintion.
  99. * @param el The predefined attributes, nested elements and text.
  100. */
  101. public PreSetDefinition(AntTypeDefinition parent, UnknownElement el) {
  102. if (parent instanceof PreSetDefinition) {
  103. PreSetDefinition p = (PreSetDefinition) parent;
  104. el.applyPreSet(p.element);
  105. parent = p.parent;
  106. }
  107. this.parent = parent;
  108. this.element = el;
  109. }
  110. /**
  111. * Override so that it is not allowed
  112. *
  113. * @param clazz a <code>Class</code> value
  114. */
  115. public void setClass(Class clazz) {
  116. throw new BuildException("Not supported");
  117. }
  118. /**
  119. * Override so that it is not allowed
  120. *
  121. * @param className a <code>String</code> value
  122. */
  123. public void setClassName(String className) {
  124. throw new BuildException("Not supported");
  125. }
  126. /**
  127. * get the classname of the definition
  128. * @return the name of the class of this definition
  129. */
  130. public String getClassName() {
  131. return parent.getClassName();
  132. }
  133. /**
  134. * set the adapter class for this definition.
  135. * NOTE Supported
  136. * @param adapterClass the adapterClass
  137. */
  138. public void setAdapterClass(Class adapterClass) {
  139. throw new BuildException("Not supported");
  140. }
  141. /**
  142. * set the assignable class for this definition.
  143. * NOT SUPPORTED
  144. * @param adaptToClass the assignable class
  145. */
  146. public void setAdaptToClass(Class adaptToClass) {
  147. throw new BuildException("Not supported");
  148. }
  149. /**
  150. * set the classloader to use to create an instance
  151. * of the definition
  152. * @param classLoader the classLoader
  153. */
  154. public void setClassLoader(ClassLoader classLoader) {
  155. throw new BuildException("Not supported");
  156. }
  157. /**
  158. * get the classloader for this definition
  159. * @return the classloader for this definition
  160. */
  161. public ClassLoader getClassLoader() {
  162. return parent.getClassLoader();
  163. }
  164. /**
  165. * get the exposed class for this definition.
  166. * @param project the current project
  167. * @return the exposed class
  168. */
  169. public Class getExposedClass(Project project) {
  170. return parent.getExposedClass(project);
  171. }
  172. /**
  173. * get the definition class
  174. * @param project the current project
  175. * @return the type of the definition
  176. */
  177. public Class getTypeClass(Project project) {
  178. return parent.getTypeClass(project);
  179. }
  180. /**
  181. * check if the attributes are correct
  182. * @param project the current project
  183. */
  184. public void checkClass(Project project) {
  185. parent.checkClass(project);
  186. }
  187. /**
  188. * create an instance of the definition.
  189. * The instance may be wrapped in a proxy class.
  190. * This is a special version of create for IH and UE.
  191. * @param project the current project
  192. * @return the created object
  193. */
  194. public Object createObject(Project project) {
  195. Object o = parent.create(project);
  196. if (o == null) {
  197. return null;
  198. }
  199. return o;
  200. }
  201. /**
  202. * @return the predefined attributes, elements and text as
  203. * a UnknownElement
  204. */
  205. public UnknownElement getPreSets() {
  206. return element;
  207. }
  208. /**
  209. * Fake create an object, used by IH and UE to see that
  210. * this is a predefined object.
  211. *
  212. * @param project the current project
  213. * @return this object
  214. */
  215. public Object create(Project project) {
  216. return this;
  217. }
  218. /**
  219. * Equality method for this definition
  220. *
  221. * @param other another definition
  222. * @param project the current project
  223. * @return true if the definitions are the same
  224. */
  225. public boolean sameDefinition(AntTypeDefinition other, Project project) {
  226. if (other == null) {
  227. return false;
  228. }
  229. if (other.getClass() != getClass()) {
  230. return false;
  231. }
  232. PreSetDefinition otherDef = (PreSetDefinition) other;
  233. if (!parent.sameDefinition(otherDef.parent, project)) {
  234. return false;
  235. }
  236. if (!element.similar(otherDef.element)) {
  237. return false;
  238. }
  239. return true;
  240. }
  241. /**
  242. * Similar method for this definition
  243. *
  244. * @param other another definition
  245. * @param project the current project
  246. * @return true if the definitions are the same
  247. */
  248. public boolean similarDefinition(
  249. AntTypeDefinition other, Project project) {
  250. if (other == null) {
  251. return false;
  252. }
  253. if (!other.getClass().getName().equals(getClass().getName())) {
  254. return false;
  255. }
  256. PreSetDefinition otherDef = (PreSetDefinition) other;
  257. if (!parent.similarDefinition(otherDef.parent, project)) {
  258. return false;
  259. }
  260. if (!element.similar(otherDef.element)) {
  261. return false;
  262. }
  263. return true;
  264. }
  265. }
  266. }