aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/UnknownElement.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/UnknownElement.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/UnknownElement.java699
1 files changed, 699 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/UnknownElement.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/UnknownElement.java
new file mode 100644
index 00000000..88cd4989
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/UnknownElement.java
@@ -0,0 +1,699 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tools.ant.taskdefs.PreSetDef;
+
+/**
+ * Wrapper class that holds all the information necessary to create a task
+ * or data type that did not exist when Ant started, or one which
+ * has had its definition updated to use a different implementation class.
+ *
+ */
+public class UnknownElement extends Task {
+
+ /**
+ * Holds the name of the task/type or nested child element of a
+ * task/type that hasn't been defined at parser time or has
+ * been redefined since original creation.
+ */
+ private final String elementName;
+
+ /**
+ * Holds the namespace of the element.
+ */
+ private String namespace = "";
+
+ /**
+ * Holds the namespace qname of the element.
+ */
+ private String qname;
+
+ /**
+ * The real object after it has been loaded.
+ */
+ private Object realThing;
+
+ /**
+ * List of child elements (UnknownElements).
+ */
+ private List<UnknownElement> children = null;
+
+ /** Specifies if a predefined definition has been done */
+ private boolean presetDefed = false;
+
+ /**
+ * Creates an UnknownElement for the given element name.
+ *
+ * @param elementName The name of the unknown element.
+ * Must not be <code>null</code>.
+ */
+ public UnknownElement(String elementName) {
+ this.elementName = elementName;
+ }
+
+ /**
+ * @return the list of nested UnknownElements for this UnknownElement.
+ */
+ public List<UnknownElement> getChildren() {
+ return children;
+ }
+
+ /**
+ * Returns the name of the XML element which generated this unknown
+ * element.
+ *
+ * @return the name of the XML element which generated this unknown
+ * element.
+ */
+ public String getTag() {
+ return elementName;
+ }
+
+ /**
+ * Return the namespace of the XML element associated with this component.
+ *
+ * @return Namespace URI used in the xmlns declaration.
+ */
+ public String getNamespace() {
+ return namespace;
+ }
+
+ /**
+ * Set the namespace of the XML element associated with this component.
+ * This method is typically called by the XML processor.
+ * If the namespace is "ant:current", the component helper
+ * is used to get the current antlib uri.
+ *
+ * @param namespace URI used in the xmlns declaration.
+ */
+ public void setNamespace(String namespace) {
+ if (namespace.equals(ProjectHelper.ANT_CURRENT_URI)) {
+ ComponentHelper helper = ComponentHelper.getComponentHelper(
+ getProject());
+ namespace = helper.getCurrentAntlibUri();
+ }
+ this.namespace = namespace == null ? "" : namespace;
+ }
+
+ /**
+ * Return the qname of the XML element associated with this component.
+ *
+ * @return namespace Qname used in the element declaration.
+ */
+ public String getQName() {
+ return qname;
+ }
+
+ /**
+ * Set the namespace qname of the XML element.
+ * This method is typically called by the XML processor.
+ *
+ * @param qname the qualified name of the element
+ */
+ public void setQName(String qname) {
+ this.qname = qname;
+ }
+
+
+ /**
+ * Get the RuntimeConfigurable instance for this UnknownElement, containing
+ * the configuration information.
+ *
+ * @return the configuration info.
+ */
+ public RuntimeConfigurable getWrapper() {
+ return super.getWrapper();
+ }
+
+ /**
+ * Creates the real object instance and child elements, then configures
+ * the attributes and text of the real object. This unknown element
+ * is then replaced with the real object in the containing target's list
+ * of children.
+ *
+ * @exception BuildException if the configuration fails
+ */
+ public void maybeConfigure() throws BuildException {
+ if (realThing != null) {
+ return;
+ }
+ configure(makeObject(this, getWrapper()));
+ }
+
+ /**
+ * Configure the given object from this UnknownElement
+ *
+ * @param realObject the real object this UnknownElement is representing.
+ *
+ */
+ public void configure(Object realObject) {
+ if (realObject == null) {
+ return;
+ }
+ realThing = realObject;
+
+ getWrapper().setProxy(realThing);
+ Task task = null;
+ if (realThing instanceof Task) {
+ task = (Task) realThing;
+
+ task.setRuntimeConfigurableWrapper(getWrapper());
+
+ // For Script example that modifies id'ed tasks in other
+ // targets to work. *very* Ugly
+ // The reference is replaced by RuntimeConfigurable
+ if (getWrapper().getId() != null) {
+ this.getOwningTarget().replaceChild(this, (Task) realThing);
+ }
+ }
+
+
+ // configure attributes of the object and it's children. If it is
+ // a task container, defer the configuration till the task container
+ // attempts to use the task
+
+ if (task != null) {
+ task.maybeConfigure();
+ } else {
+ getWrapper().maybeConfigure(getProject());
+ }
+
+ handleChildren(realThing, getWrapper());
+ }
+
+ /**
+ * Handles output sent to System.out by this task or its real task.
+ *
+ * @param output The output to log. Should not be <code>null</code>.
+ */
+ protected void handleOutput(String output) {
+ if (realThing instanceof Task) {
+ ((Task) realThing).handleOutput(output);
+ } else {
+ super.handleOutput(output);
+ }
+ }
+
+ /**
+ * Delegate to realThing if present and if it as task.
+ * @see Task#handleInput(byte[], int, int)
+ * @param buffer the buffer into which data is to be read.
+ * @param offset the offset into the buffer at which data is stored.
+ * @param length the amount of data to read.
+ *
+ * @return the number of bytes read.
+ *
+ * @exception IOException if the data cannot be read.
+ * @since Ant 1.6
+ */
+ protected int handleInput(byte[] buffer, int offset, int length)
+ throws IOException {
+ if (realThing instanceof Task) {
+ return ((Task) realThing).handleInput(buffer, offset, length);
+ } else {
+ return super.handleInput(buffer, offset, length);
+ }
+
+ }
+
+ /**
+ * Handles output sent to System.out by this task or its real task.
+ *
+ * @param output The output to log. Should not be <code>null</code>.
+ */
+ protected void handleFlush(String output) {
+ if (realThing instanceof Task) {
+ ((Task) realThing).handleFlush(output);
+ } else {
+ super.handleFlush(output);
+ }
+ }
+
+ /**
+ * Handles error output sent to System.err by this task or its real task.
+ *
+ * @param output The error output to log. Should not be <code>null</code>.
+ */
+ protected void handleErrorOutput(String output) {
+ if (realThing instanceof Task) {
+ ((Task) realThing).handleErrorOutput(output);
+ } else {
+ super.handleErrorOutput(output);
+ }
+ }
+
+ /**
+ * Handles error output sent to System.err by this task or its real task.
+ *
+ * @param output The error output to log. Should not be <code>null</code>.
+ */
+ protected void handleErrorFlush(String output) {
+ if (realThing instanceof Task) {
+ ((Task) realThing).handleErrorFlush(output);
+ } else {
+ super.handleErrorFlush(output);
+ }
+ }
+
+ /**
+ * Executes the real object if it's a task. If it's not a task
+ * (e.g. a data type) then this method does nothing.
+ */
+ public void execute() {
+ if (realThing == null) {
+ // Got here if the runtimeconfigurable is not enabled.
+ return;
+ }
+ try {
+ if (realThing instanceof Task) {
+ ((Task) realThing).execute();
+ }
+ } finally {
+ // Finished executing the task
+ // null it (unless it has an ID) to allow
+ // GC do its job
+ // If this UE is used again, a new "realthing" will be made
+ if (getWrapper().getId() == null) {
+ realThing = null;
+ getWrapper().setProxy(null);
+ }
+ }
+ }
+
+ /**
+ * Adds a child element to this element.
+ *
+ * @param child The child element to add. Must not be <code>null</code>.
+ */
+ public void addChild(UnknownElement child) {
+ if (children == null) {
+ children = new ArrayList<UnknownElement>();
+ }
+ children.add(child);
+ }
+
+ /**
+ * Creates child elements, creates children of the children
+ * (recursively), and sets attributes of the child elements.
+ *
+ * @param parent The configured object for the parent.
+ * Must not be <code>null</code>.
+ *
+ * @param parentWrapper The wrapper containing child wrappers
+ * to be configured. Must not be <code>null</code>
+ * if there are any children.
+ *
+ * @exception BuildException if the children cannot be configured.
+ */
+ protected void handleChildren(
+ Object parent,
+ RuntimeConfigurable parentWrapper)
+ throws BuildException {
+ if (parent instanceof TypeAdapter) {
+ parent = ((TypeAdapter) parent).getProxy();
+ }
+
+ String parentUri = getNamespace();
+ Class<?> parentClass = parent.getClass();
+ IntrospectionHelper ih = IntrospectionHelper.getHelper(getProject(), parentClass);
+
+
+ if (children != null) {
+ Iterator<UnknownElement> it = children.iterator();
+ for (int i = 0; it.hasNext(); i++) {
+ RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
+ UnknownElement child = it.next();
+ try {
+ if (!childWrapper.isEnabled(child)) {
+ if (ih.supportsNestedElement(
+ parentUri, ProjectHelper.genComponentName(
+ child.getNamespace(), child.getTag()))) {
+ continue;
+ }
+ // fall tru and fail in handlechild (unsupported element)
+ }
+ if (!handleChild(
+ parentUri, ih, parent, child, childWrapper)) {
+ if (!(parent instanceof TaskContainer)) {
+ ih.throwNotSupported(getProject(), parent,
+ child.getTag());
+ } else {
+ // a task container - anything could happen - just add the
+ // child to the container
+ TaskContainer container = (TaskContainer) parent;
+ container.addTask(child);
+ }
+ }
+ } catch (UnsupportedElementException ex) {
+ throw new BuildException(
+ parentWrapper.getElementTag()
+ + " doesn't support the nested \"" + ex.getElement()
+ + "\" element.", ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return the component name - uses ProjectHelper#genComponentName()
+ */
+ protected String getComponentName() {
+ return ProjectHelper.genComponentName(getNamespace(), getTag());
+ }
+
+ /**
+ * This is used then the realobject of the UE is a PreSetDefinition.
+ * This is also used when a presetdef is used on a presetdef
+ * The attributes, elements and text are applied to this
+ * UE.
+ *
+ * @param u an UnknownElement containing the attributes, elements and text
+ */
+ public void applyPreSet(UnknownElement u) {
+ if (presetDefed) {
+ return;
+ }
+ // Do the runtime
+ getWrapper().applyPreSet(u.getWrapper());
+ if (u.children != null) {
+ List<UnknownElement> newChildren = new ArrayList<UnknownElement>();
+ newChildren.addAll(u.children);
+ if (children != null) {
+ newChildren.addAll(children);
+ }
+ children = newChildren;
+ }
+ presetDefed = true;
+ }
+
+ /**
+ * Creates a named task or data type. If the real object is a task,
+ * it is configured up to the init() stage.
+ *
+ * @param ue The unknown element to create the real object for.
+ * Must not be <code>null</code>.
+ * @param w Ignored in this implementation.
+ *
+ * @return the task or data type represented by the given unknown element.
+ */
+ protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
+ if (!w.isEnabled(ue)) {
+ return null;
+ }
+ ComponentHelper helper = ComponentHelper.getComponentHelper(
+ getProject());
+ String name = ue.getComponentName();
+ Object o = helper.createComponent(ue, ue.getNamespace(), name);
+ if (o == null) {
+ throw getNotFoundException("task or type", name);
+ }
+ if (o instanceof PreSetDef.PreSetDefinition) {
+ PreSetDef.PreSetDefinition def = (PreSetDef.PreSetDefinition) o;
+ o = def.createObject(ue.getProject());
+ if (o == null) {
+ throw getNotFoundException(
+ "preset " + name,
+ def.getPreSets().getComponentName());
+ }
+ ue.applyPreSet(def.getPreSets());
+ if (o instanceof Task) {
+ Task task = (Task) o;
+ task.setTaskType(ue.getTaskType());
+ task.setTaskName(ue.getTaskName());
+ task.init();
+ }
+ }
+ if (o instanceof UnknownElement) {
+ o = ((UnknownElement) o).makeObject((UnknownElement) o, w);
+ }
+ if (o instanceof Task) {
+ ((Task) o).setOwningTarget(getOwningTarget());
+ }
+ if (o instanceof ProjectComponent) {
+ ((ProjectComponent) o).setLocation(getLocation());
+ }
+ return o;
+ }
+
+ /**
+ * Creates a named task and configures it up to the init() stage.
+ *
+ * @param ue The UnknownElement to create the real task for.
+ * Must not be <code>null</code>.
+ * @param w Ignored.
+ *
+ * @return the task specified by the given unknown element, or
+ * <code>null</code> if the task name is not recognised.
+ */
+ protected Task makeTask(UnknownElement ue, RuntimeConfigurable w) {
+ Task task = getProject().createTask(ue.getTag());
+
+ if (task != null) {
+ task.setLocation(getLocation());
+ // UnknownElement always has an associated target
+ task.setOwningTarget(getOwningTarget());
+ task.init();
+ }
+ return task;
+ }
+
+ /**
+ * Returns a very verbose exception for when a task/data type cannot
+ * be found.
+ *
+ * @param what The kind of thing being created. For example, when
+ * a task name could not be found, this would be
+ * <code>"task"</code>. Should not be <code>null</code>.
+ * @param name The name of the element which could not be found.
+ * Should not be <code>null</code>.
+ *
+ * @return a detailed description of what might have caused the problem.
+ */
+ protected BuildException getNotFoundException(String what,
+ String name) {
+ ComponentHelper helper = ComponentHelper.getComponentHelper(getProject());
+ String msg = helper.diagnoseCreationFailure(name, what);
+ return new BuildException(msg, getLocation());
+ }
+
+ /**
+ * Returns the name to use in logging messages.
+ *
+ * @return the name to use in logging messages.
+ */
+ public String getTaskName() {
+ //return elementName;
+ return realThing == null
+ || !(realThing instanceof Task) ? super.getTaskName()
+ : ((Task) realThing).getTaskName();
+ }
+
+ /**
+ * Returns the task instance after it has been created and if it is a task.
+ *
+ * @return a task instance or <code>null</code> if the real object is not
+ * a task.
+ */
+ public Task getTask() {
+ if (realThing instanceof Task) {
+ return (Task) realThing;
+ }
+ return null;
+ }
+
+ /**
+ * Return the configured object
+ *
+ * @return the real thing whatever it is
+ *
+ * @since ant 1.6
+ */
+ public Object getRealThing() {
+ return realThing;
+ }
+
+ /**
+ * Set the configured object
+ * @param realThing the configured object
+ * @since ant 1.7
+ */
+ public void setRealThing(Object realThing) {
+ this.realThing = realThing;
+ }
+
+ /**
+ * Try to create a nested element of <code>parent</code> for the
+ * given tag.
+ *
+ * @return whether the creation has been successful
+ */
+ private boolean handleChild(
+ String parentUri,
+ IntrospectionHelper ih,
+ Object parent, UnknownElement child,
+ RuntimeConfigurable childWrapper) {
+ String childName = ProjectHelper.genComponentName(
+ child.getNamespace(), child.getTag());
+ if (ih.supportsNestedElement(parentUri, childName, getProject(),
+ parent)) {
+ IntrospectionHelper.Creator creator = null;
+ try {
+ creator = ih.getElementCreator(getProject(), parentUri,
+ parent, childName, child);
+ } catch (UnsupportedElementException use) {
+ if (!ih.isDynamic()) {
+ throw use;
+ }
+ // can't trust supportsNestedElement for dynamic elements
+ return false;
+ }
+ creator.setPolyType(childWrapper.getPolyType());
+ Object realChild = creator.create();
+ if (realChild instanceof PreSetDef.PreSetDefinition) {
+ PreSetDef.PreSetDefinition def =
+ (PreSetDef.PreSetDefinition) realChild;
+ realChild = creator.getRealObject();
+ child.applyPreSet(def.getPreSets());
+ }
+ childWrapper.setCreator(creator);
+ childWrapper.setProxy(realChild);
+ if (realChild instanceof Task) {
+ Task childTask = (Task) realChild;
+ childTask.setRuntimeConfigurableWrapper(childWrapper);
+ childTask.setTaskName(childName);
+ childTask.setTaskType(childName);
+ }
+ if (realChild instanceof ProjectComponent) {
+ ((ProjectComponent) realChild).setLocation(child.getLocation());
+ }
+ childWrapper.maybeConfigure(getProject());
+ child.handleChildren(realChild, childWrapper);
+ creator.store();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * like contents equals, but ignores project
+ * @param obj the object to check against
+ * @return true if this unknownelement has the same contents the other
+ */
+ public boolean similar(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!getClass().getName().equals(obj.getClass().getName())) {
+ return false;
+ }
+ UnknownElement other = (UnknownElement) obj;
+ // Are the names the same ?
+ if (!equalsString(elementName, other.elementName)) {
+ return false;
+ }
+ if (!namespace.equals(other.namespace)) {
+ return false;
+ }
+ if (!qname.equals(other.qname)) {
+ return false;
+ }
+ // Are attributes the same ?
+ if (!getWrapper().getAttributeMap().equals(
+ other.getWrapper().getAttributeMap())) {
+ return false;
+ }
+ // Is the text the same?
+ // Need to use equals on the string and not
+ // on the stringbuffer as equals on the string buffer
+ // does not compare the contents.
+ if (!getWrapper().getText().toString().equals(
+ other.getWrapper().getText().toString())) {
+ return false;
+ }
+ // Are the sub elements the same ?
+ final int childrenSize = children == null ? 0 : children.size();
+ if (childrenSize == 0) {
+ return other.children == null || other.children.size() == 0;
+ }
+ if (other.children == null) {
+ return false;
+ }
+ if (childrenSize != other.children.size()) {
+ return false;
+ }
+ for (int i = 0; i < childrenSize; ++i) {
+ UnknownElement child = (UnknownElement) children.get(i);
+ if (!child.similar(other.children.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean equalsString(String a, String b) {
+ return (a == null) ? (b == null) : a.equals(b);
+ }
+
+ /**
+ * Make a copy of the unknown element and set it in the new project.
+ * @param newProject the project to create the UE in.
+ * @return the copied UE.
+ */
+ public UnknownElement copy(Project newProject) {
+ UnknownElement ret = new UnknownElement(getTag());
+ ret.setNamespace(getNamespace());
+ ret.setProject(newProject);
+ ret.setQName(getQName());
+ ret.setTaskType(getTaskType());
+ ret.setTaskName(getTaskName());
+ ret.setLocation(getLocation());
+ if (getOwningTarget() == null) {
+ Target t = new Target();
+ t.setProject(getProject());
+ ret.setOwningTarget(t);
+ } else {
+ ret.setOwningTarget(getOwningTarget());
+ }
+ RuntimeConfigurable copyRC = new RuntimeConfigurable(
+ ret, getTaskName());
+ copyRC.setPolyType(getWrapper().getPolyType());
+ Map<String, Object> m = getWrapper().getAttributeMap();
+ for (Map.Entry<String, Object> entry : m.entrySet()) {
+ copyRC.setAttribute(entry.getKey(), (String) entry.getValue());
+ }
+ copyRC.addText(getWrapper().getText().toString());
+
+ for (Enumeration<RuntimeConfigurable> e = getWrapper().getChildren(); e.hasMoreElements();) {
+ RuntimeConfigurable r = e.nextElement();
+ UnknownElement ueChild = (UnknownElement) r.getProxy();
+ UnknownElement copyChild = ueChild.copy(newProject);
+ copyRC.addChild(copyChild.getWrapper());
+ ret.addChild(copyChild);
+ }
+ return ret;
+ }
+}