From d06d2aa4fb6362b1b0298fa1405909c615df9a63 Mon Sep 17 00:00:00 2001 From: Costin Manolache Date: Fri, 11 Oct 2002 17:57:56 +0000 Subject: [PATCH] Added an alternate implementation, so we can override default behavior and control the creation. This will work for all code that checks instanceof, but will obviously fail if any code explicitely looks at the class name ( which is very unlikely - so far no code did that in the gump run or otherwise ). The UnknownElement2/RuntimeConfigurable2 will be further refactored to make them more independent of the XML representation and have a cleaner API. All behavior will be moved out of the XML processor and into this pair. Of course, full backward compat will be provided. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273432 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/UnknownElement2.java | 325 ++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 proposal/embed/src/java/org/apache/tools/ant/UnknownElement2.java diff --git a/proposal/embed/src/java/org/apache/tools/ant/UnknownElement2.java b/proposal/embed/src/java/org/apache/tools/ant/UnknownElement2.java new file mode 100644 index 000000000..fa6efc0d6 --- /dev/null +++ b/proposal/embed/src/java/org/apache/tools/ant/UnknownElement2.java @@ -0,0 +1,325 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant; +import org.apache.tools.ant.*; + +import java.util.Vector; + +// XXX Use this as a replacement for the adapter ! + +/** + * Wrapper class that holds all the information necessary to create a task + * or data type. + * + * With PH2, all components will be wrapped. Long term we should consolidate + * UnkndownElement and RuntimeConfigurable. + * + * @author Stefan Bodewig + * @author Costin Manolache + * + * @deprecated All tasks will be lazily created and configured before execution. + * The xml reader will create a tree of RuntimeConfigurable, and tasks will + * be constructed ( and reconstructed for loops ) just before execution. The + * UnknonwnElement construct is no longer needed. + */ +public class UnknownElement2 extends UnknownElement { + + /** + * 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 String elementName; + + /** + * The real object after it has been loaded. + */ + private Object realThing; + + /** + * List of child elements (UnknownElements). + */ + private Vector children = new Vector(); + + /** + * Creates an UnknownElement for the given element name. + * + * @param elementName The name of the unknown element. + * Must not be null. + */ + public UnknownElement2(String elementName) { + super( elementName ); + this.elementName = elementName; + } + + /** + * 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; + } + + protected RuntimeConfigurable getWrapper() { + return wrapper; + } + + protected RuntimeConfigurable2 getWrapper2() { + return (RuntimeConfigurable2)wrapper; + } + + + /** + * 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 { + ProjectComponentHelper helper=ProjectComponentHelper.getProjectComponentHelper(); + // Used to be: makeObject(this, getWrapper2()); + realThing = helper.createProjectComponent( this, getProject(), null, + this.getTag()); + if (realThing == null) { + throw getNotFoundException("task or type", this.getTag()); + } + + getWrapper2().setProxy(realThing); + + if (realThing instanceof Task) { + Task task=(Task)realThing; + task.setLocation(this.getLocation()); + // UnknownElement always has an associated target + task.setOwningTarget(this.getOwningTarget()); + task.init(); + task.setRuntimeConfigurableWrapper(getWrapper2()); + } + + handleChildren(realThing, getWrapper2()); + + getWrapper2().maybeConfigure(getProject()); + } + + /** + * Handles output sent to System.out by this task or its real task. + * + * @param line The line of output to log. Should not be null. + */ + protected void handleOutput(String line) { + if (realThing instanceof Task) { + ((Task) realThing).handleOutput(line); + } else { + super.handleOutput(line); + } + } + + /** + * Handles error output sent to System.err by this task or its real task. + * + * @param line The error line to log. Should not be null. + */ + protected void handleErrorOutput(String line) { + if (realThing instanceof Task) { + ((Task) realThing).handleErrorOutput(line); + } else { + super.handleErrorOutput(line); + } + } + + /** + * 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) { + // plain impossible to get here, maybeConfigure should + // have thrown an exception. + throw new BuildException("Could not create task of type: " + + elementName, getLocation()); + } + + if (realThing instanceof Task) { + ((Task) realThing).execute(); + } + } + + /** + * Adds a child element to this element. + * + * @param child The child element to add. Must not be null. + */ + public void addChild(UnknownElement child) { + children.addElement(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 null. + * + * @param parentWrapper The wrapper containing child wrappers + * to be configured. Must not be null + * 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 TaskAdapter) { + parent = ((TaskAdapter) parent).getProxy(); + } + + Class parentClass = parent.getClass(); + IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass); + + for (int i = 0; i < children.size(); i++) { + RuntimeConfigurable childWrapper = parentWrapper.getChild(i); + UnknownElement child = (UnknownElement) children.elementAt(i); + Object realChild = null; + + if (parent instanceof TaskContainer) { + ProjectComponentHelper helper=ProjectComponentHelper.getProjectComponentHelper(); + // Used to be: makeTask(child, childWrapper, false); + realChild = helper.createProjectComponent( child, getProject(), null, + child.getTag()); + if (realChild == null ) { + throw getNotFoundException("task", child.getTag()); + } + + // XXX DataTypes will be wrapped or treated like normal components + if( realChild instanceof Task ) { + ((TaskContainer) parent).addTask((Task) realChild); + Task task=(Task)realChild; + task.setLocation(child.getLocation()); + // UnknownElement always has an associated target + task.setOwningTarget(this.getOwningTarget()); + task.init(); + } else { + // What ? Add data type ? createElement ? + } + } else { + // Introspection-based task creation + realChild = ih.createElement(getProject(), parent, child.getTag()); + } + + childWrapper.setProxy(realChild); + if (parent instanceof TaskContainer) { + ((Task) realChild).setRuntimeConfigurableWrapper(childWrapper); + } + + child.handleChildren(realChild, childWrapper); + + if (parent instanceof TaskContainer) { + ((Task) realChild).maybeConfigure(); + } + } + } + + /** + * @deprecated no longer used + */ + protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) { + /*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();} + return null; + } + + /** + * @deprecated no longer used + */ + protected Task makeTask(UnknownElement ue, RuntimeConfigurable w, + boolean onTopLevel) { + /*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();} + return null; + } + + + /** + * Returns the name to use in logging messages. + * + * @return the name to use in logging messages. + */ + public String getTaskName() { + return elementName; // cleaner, works for everything + // return realThing == null || !(realThing instanceof Task) ? + // super.getTaskName() : ((Task) realThing).getTaskName(); + } + + public Object getWrapped() { + return realThing; + } + + /** + * returns the task instance after it has been created and if it is a task. + * + * @return a task instance or null if the real object is not + * a task. + */ + public Task getTask() { + if (realThing instanceof Task) { + return (Task) realThing; + } + return null; + } + +}// UnknownElement