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.taskdefs;
020:
021: import org.apache.tools.ant.AntTypeDefinition;
022: import org.apache.tools.ant.BuildException;
023: import org.apache.tools.ant.ComponentHelper;
024: import org.apache.tools.ant.Project;
025: import org.apache.tools.ant.ProjectHelper;
026: import org.apache.tools.ant.Task;
027: import org.apache.tools.ant.TaskContainer;
028: import org.apache.tools.ant.UnknownElement;
029:
030: /**
031: * The preset definition task generates a new definition
032: * based on a current definition with some attributes or
033: * elements preset.
034: * <pre>
035: * <presetdef name="my.javac">
036: * <javac deprecation="${deprecation}" debug="${debug}"/>
037: * </presetdef>
038: * <my.javac srcdir="src" destdir="classes"/>
039: * </pre>
040: *
041: * @since Ant 1.6
042: */
043: public class PreSetDef extends AntlibDefinition implements
044: TaskContainer {
045: private UnknownElement nestedTask;
046: private String name;
047:
048: /**
049: * Set the name of this definition.
050: * @param name the name of the definition.
051: */
052: public void setName(String name) {
053: this .name = name;
054: }
055:
056: /**
057: * Add a nested task to predefine attributes and elements on.
058: * @param nestedTask Nested task/type to extend.
059: */
060: public void addTask(Task nestedTask) {
061: if (this .nestedTask != null) {
062: throw new BuildException("Only one nested element allowed");
063: }
064: if (!(nestedTask instanceof UnknownElement)) {
065: throw new BuildException(
066: "addTask called with a task that is not an unknown element");
067: }
068: this .nestedTask = (UnknownElement) nestedTask;
069: }
070:
071: /**
072: * Make a new definition.
073: */
074: public void execute() {
075: if (nestedTask == null) {
076: throw new BuildException("Missing nested element");
077: }
078: if (name == null) {
079: throw new BuildException("Name not specified");
080: }
081: name = ProjectHelper.genComponentName(getURI(), name);
082:
083: ComponentHelper helper = ComponentHelper
084: .getComponentHelper(getProject());
085:
086: String componentName = ProjectHelper.genComponentName(
087: nestedTask.getNamespace(), nestedTask.getTag());
088:
089: AntTypeDefinition def = helper.getDefinition(componentName);
090: if (def == null) {
091: throw new BuildException("Unable to find typedef "
092: + componentName);
093: }
094: PreSetDefinition newDef = new PreSetDefinition(def, nestedTask);
095:
096: newDef.setName(name);
097:
098: helper.addDataTypeDefinition(newDef);
099: log("defining preset " + name, Project.MSG_VERBOSE);
100: }
101:
102: /**
103: * This class contains the unknown element and the object
104: * that is predefined.
105: * @see AntTypeDefinition
106: */
107: public static class PreSetDefinition extends AntTypeDefinition {
108: private AntTypeDefinition parent;
109: private UnknownElement element;
110:
111: /**
112: * Creates a new <code>PresetDefinition</code> instance.
113: *
114: * @param parent The parent of this predefinition.
115: * @param el The predefined attributes, nested elements and text.
116: */
117: public PreSetDefinition(AntTypeDefinition parent,
118: UnknownElement el) {
119: if (parent instanceof PreSetDefinition) {
120: PreSetDefinition p = (PreSetDefinition) parent;
121: el.applyPreSet(p.element);
122: parent = p.parent;
123: }
124: this .parent = parent;
125: this .element = el;
126: }
127:
128: /**
129: * Override so that it is not allowed.
130: *
131: * @param clazz a <code>Class</code> value.
132: */
133: public void setClass(Class clazz) {
134: throw new BuildException("Not supported");
135: }
136:
137: /**
138: * Override so that it is not allowed.
139: *
140: * @param className a <code>String</code> value.
141: */
142: public void setClassName(String className) {
143: throw new BuildException("Not supported");
144: }
145:
146: /**
147: * Get the classname of the definition.
148: * @return the name of the class of this definition.
149: */
150: public String getClassName() {
151: return parent.getClassName();
152: }
153:
154: /**
155: * Set the adapter class for this definition.
156: * NOT Supported
157: * @param adapterClass the adapterClass.
158: */
159: public void setAdapterClass(Class adapterClass) {
160: throw new BuildException("Not supported");
161: }
162:
163: /**
164: * Set the assignable class for this definition.
165: * NOT SUPPORTED
166: * @param adaptToClass the assignable class.
167: */
168: public void setAdaptToClass(Class adaptToClass) {
169: throw new BuildException("Not supported");
170: }
171:
172: /**
173: * Set the classloader to use to create an instance
174: * of the definition.
175: * NOT SUPPORTED
176: * @param classLoader the classLoader.
177: */
178: public void setClassLoader(ClassLoader classLoader) {
179: throw new BuildException("Not supported");
180: }
181:
182: /**
183: * Get the classloader for this definition.
184: * @return the classloader for this definition.
185: */
186: public ClassLoader getClassLoader() {
187: return parent.getClassLoader();
188: }
189:
190: /**
191: * Get the exposed class for this definition.
192: * @param project the current project.
193: * @return the exposed class.
194: */
195: public Class getExposedClass(Project project) {
196: return parent.getExposedClass(project);
197: }
198:
199: /**
200: * Get the definition class.
201: * @param project the current project.
202: * @return the type of the definition.
203: */
204: public Class getTypeClass(Project project) {
205: return parent.getTypeClass(project);
206: }
207:
208: /**
209: * Check if the attributes are correct.
210: * @param project the current project.
211: */
212: public void checkClass(Project project) {
213: parent.checkClass(project);
214: }
215:
216: /**
217: * Create an instance of the definition. The instance may be wrapped
218: * in a proxy class. This is a special version of create for
219: * IntrospectionHelper and UnknownElement.
220: * @param project the current project.
221: * @return the created object.
222: */
223: public Object createObject(Project project) {
224: return parent.create(project);
225: }
226:
227: /**
228: * Get the preset values.
229: * @return the predefined attributes, elements and text as
230: * an UnknownElement.
231: */
232: public UnknownElement getPreSets() {
233: return element;
234: }
235:
236: /**
237: * Fake create an object, used by IntrospectionHelper and UnknownElement
238: * to see that this is a predefined object.
239: *
240: * @param project the current project.
241: * @return this object.
242: */
243: public Object create(Project project) {
244: return this ;
245: }
246:
247: /**
248: * Equality method for this definition.
249: *
250: * @param other another definition.
251: * @param project the current project.
252: * @return true if the definitions are the same.
253: */
254: public boolean sameDefinition(AntTypeDefinition other,
255: Project project) {
256: return (other != null
257: && other.getClass() == getClass()
258: && parent != null
259: && parent.sameDefinition(
260: ((PreSetDefinition) other).parent, project) && element
261: .similar(((PreSetDefinition) other).element));
262: }
263:
264: /**
265: * Similar method for this definition.
266: *
267: * @param other another definition.
268: * @param project the current project.
269: * @return true if the definitions are similar.
270: */
271: public boolean similarDefinition(AntTypeDefinition other,
272: Project project) {
273: return (other != null
274: && other.getClass().getName().equals(
275: getClass().getName())
276: && parent != null
277: && parent.similarDefinition(
278: ((PreSetDefinition) other).parent, project) && element
279: .similar(((PreSetDefinition) other).element));
280: }
281: }
282: }
|