Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 412   Methods: 17
NCLOC: 173   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
UnknownElement.java 67.6% 80.6% 82.4% 77.2%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant;
 56   
 
 57   
 import java.util.Vector;
 58   
 import java.io.IOException;
 59   
 
 60   
 /**
 61   
  * Wrapper class that holds all the information necessary to create a task
 62   
  * or data type that did not exist when Ant started, or one which
 63   
  * has had its definition updated to use a different implementation class.
 64   
  *
 65   
  * @author Stefan Bodewig
 66   
  */
 67   
 public class UnknownElement extends Task {
 68   
 
 69   
     /**
 70   
      * Holds the name of the task/type or nested child element of a
 71   
      * task/type that hasn't been defined at parser time or has
 72   
      * been redefined since original creation.
 73   
      */
 74   
     private String elementName;
 75   
 
 76   
     /**
 77   
      * The real object after it has been loaded.
 78   
      */
 79   
     private Object realThing;
 80   
 
 81   
     /**
 82   
      * List of child elements (UnknownElements).
 83   
      */
 84   
     private Vector children = new Vector();
 85   
 
 86   
     /**
 87   
      * Creates an UnknownElement for the given element name.
 88   
      *
 89   
      * @param elementName The name of the unknown element.
 90   
      *                    Must not be <code>null</code>.
 91   
      */
 92  22085
     public UnknownElement (String elementName) {
 93  22085
         this.elementName = elementName;
 94   
     }
 95   
 
 96   
     /**
 97   
      * Returns the name of the XML element which generated this unknown
 98   
      * element.
 99   
      *
 100   
      * @return the name of the XML element which generated this unknown
 101   
      *         element.
 102   
      */
 103  5251
     public String getTag() {
 104  5251
         return elementName;
 105   
     }
 106   
 
 107  16005
     public RuntimeConfigurable getWrapper() {
 108  16005
         return wrapper;
 109   
     }
 110   
 
 111   
     /**
 112   
      * Creates the real object instance and child elements, then configures
 113   
      * the attributes and text of the real object. This unknown element
 114   
      * is then replaced with the real object in the containing target's list
 115   
      * of children.
 116   
      *
 117   
      * @exception BuildException if the configuration fails
 118   
      */
 119  3235
     public void maybeConfigure() throws BuildException {
 120   
         //ProjectComponentHelper helper=ProjectComponentHelper.getProjectComponentHelper();
 121   
         //realThing = helper.createProjectComponent( this, getProject(), null,
 122   
         //                                           this.getTag());
 123   
 
 124  3235
         realThing = makeObject(this, getWrapper());
 125   
 
 126  3234
         getWrapper().setProxy(realThing);
 127  3234
         if (realThing instanceof Task) {
 128  3062
             Task task = (Task) realThing;
 129   
 
 130  3062
             task.setRuntimeConfigurableWrapper(getWrapper());
 131   
 
 132   
             // For Script to work. Ugly
 133   
             // The reference is replaced by RuntimeConfigurable
 134  3062
             this.getOwningTarget().replaceChild(this, (Task) realThing);
 135   
         }
 136   
 
 137  3234
         handleChildren(realThing, getWrapper());
 138   
 
 139   
         // configure attributes of the object and it's children. If it is
 140   
         // a task container, defer the configuration till the task container
 141   
         // attempts to use the task
 142  3234
         getWrapper().maybeConfigure(getProject());
 143   
     }
 144   
 
 145   
     /**
 146   
      * Handles output sent to System.out by this task or its real task.
 147   
      *
 148   
      * @param line The line of output to log. Should not be <code>null</code>.
 149   
      */
 150  250
     protected void handleOutput(String line) {
 151  250
         if (realThing instanceof Task) {
 152  250
             ((Task) realThing).handleOutput(line);
 153   
         } else {
 154  0
             super.handleOutput(line);
 155   
         }
 156   
     }
 157   
 
 158   
     /**
 159   
      * @see Task#handleInput(byte[], int, int)
 160   
      * 
 161   
      * @since Ant 1.6
 162   
      */
 163  0
     protected int handleInput(byte[] buffer, int offset, int length) 
 164   
         throws IOException {
 165  0
         if (realThing instanceof Task) {
 166  0
             return ((Task) realThing).handleInput(buffer, offset, length);
 167   
         } else {
 168  0
             return super.handleInput(buffer, offset, length);
 169   
         }
 170   
             
 171   
     }
 172   
     /**
 173   
      * Handles output sent to System.out by this task or its real task.
 174   
      *
 175   
      * @param line The line of output to log. Should not be <code>null</code>.
 176   
      */
 177  0
     protected void handleFlush(String line) {
 178  0
         if (realThing instanceof Task) {
 179  0
             ((Task) realThing).handleFlush(line);
 180   
         } else {
 181  0
             super.handleFlush(line);
 182   
         }
 183   
     }
 184   
 
 185   
     /**
 186   
      * Handles error output sent to System.err by this task or its real task.
 187   
      *
 188   
      * @param line The error line to log. Should not be <code>null</code>.
 189   
      */
 190  33
     protected void handleErrorOutput(String line) {
 191  33
         if (realThing instanceof Task) {
 192  33
             ((Task) realThing).handleErrorOutput(line);
 193   
         } else {
 194  0
             super.handleErrorOutput(line);
 195   
         }
 196   
     }
 197   
 
 198   
 
 199   
     /**
 200   
      * Handles error output sent to System.err by this task or its real task.
 201   
      *
 202   
      * @param line The error line to log. Should not be <code>null</code>.
 203   
      */
 204  0
     protected void handleErrorFlush(String line) {
 205  0
         if (realThing instanceof Task) {
 206  0
             ((Task) realThing).handleErrorOutput(line);
 207   
         } else {
 208  0
             super.handleErrorOutput(line);
 209   
         }
 210   
     }
 211   
     
 212   
     /**
 213   
      * Executes the real object if it's a task. If it's not a task
 214   
      * (e.g. a data type) then this method does nothing.
 215   
      */
 216  3216
     public void execute() {
 217  3216
         if (realThing == null) {
 218   
             // plain impossible to get here, maybeConfigure should
 219   
             // have thrown an exception.
 220  0
             throw new BuildException("Could not create task of type: "
 221   
                                      + elementName, getLocation());
 222   
         }
 223   
 
 224  3216
         if (realThing instanceof Task) {
 225  3044
             ((Task) realThing).execute();
 226   
         }
 227   
 
 228   
         // the task will not be reused ( a new init() will be called )
 229   
         // Let GC do its job
 230  3087
         realThing = null;
 231   
     }
 232   
 
 233   
     /**
 234   
      * Adds a child element to this element.
 235   
      *
 236   
      * @param child The child element to add. Must not be <code>null</code>.
 237   
      */
 238  7448
     public void addChild(UnknownElement child) {
 239  7448
         children.addElement(child);
 240   
     }
 241   
 
 242   
     /**
 243   
      * Creates child elements, creates children of the children
 244   
      * (recursively), and sets attributes of the child elements.
 245   
      *
 246   
      * @param parent The configured object for the parent.
 247   
      *               Must not be <code>null</code>.
 248   
      *
 249   
      * @param parentWrapper The wrapper containing child wrappers
 250   
      *                      to be configured. Must not be <code>null</code>
 251   
      *                      if there are any children.
 252   
      *
 253   
      * @exception BuildException if the children cannot be configured.
 254   
      */
 255  4083
     protected void handleChildren(Object parent,
 256   
                                   RuntimeConfigurable parentWrapper)
 257   
         throws BuildException {
 258  4083
         if (parent instanceof TaskAdapter) {
 259  66
             parent = ((TaskAdapter) parent).getProxy();
 260   
         }
 261   
 
 262  4083
         Class parentClass = parent.getClass();
 263  4083
         IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass);
 264   
 
 265  4083
         for (int i = 0;  i < children.size(); i++) {
 266  933
             RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
 267  933
             UnknownElement child = (UnknownElement) children.elementAt(i);
 268  933
             Object realChild = null;
 269   
 
 270  933
             if (ih.supportsNestedElement(child.getTag())) { 
 271  849
                 realChild 
 272   
                     = ih.createElement(getProject(), parent, child.getTag());
 273  849
                 childWrapper.setProxy(realChild);
 274  849
                 if (realChild instanceof Task) {
 275  30
                     Task childTask = (Task) realChild;
 276  30
                     childTask.setRuntimeConfigurableWrapper(childWrapper);
 277  30
                     childTask.setTaskName(child.getTag());
 278  30
                     childTask.setTaskType(child.getTag());
 279   
                 }
 280  849
                 child.handleChildren(realChild, childWrapper);
 281   
 
 282  84
             } else if (!(parent instanceof TaskContainer)) {
 283  0
                 ih.throwNotSupported(getProject(), parent, child.getTag());
 284   
             } else {
 285   
                 // a task container - anything could happen - just add the 
 286   
                 // child to the container
 287  84
                 TaskContainer container = (TaskContainer) parent;
 288  84
                 container.addTask(child);
 289   
             }                
 290   
         }
 291   
     }
 292   
 
 293   
     /**
 294   
      * Creates a named task or data type. If the real object is a task,
 295   
      * it is configured up to the init() stage.
 296   
      *
 297   
      * @param ue The unknown element to create the real object for.
 298   
      *           Must not be <code>null</code>.
 299   
      * @param w  Ignored in this implementation.
 300   
      *
 301   
      * @return the task or data type represented by the given unknown element.
 302   
      */
 303  3235
     protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
 304  3235
         Object o = makeTask(ue, w);
 305  3235
         if (o == null) {
 306  173
             o = getProject().createDataType(ue.getTag());
 307   
         }
 308  3235
         if (o == null) {
 309  1
             throw getNotFoundException("task or type", ue.getTag());
 310   
         }
 311  3234
         return o;
 312   
     }
 313   
 
 314   
     /**
 315   
      * Creates a named task and configures it up to the init() stage.
 316   
      *
 317   
      * @param ue The UnknownElement to create the real task for.
 318   
      *           Must not be <code>null</code>.
 319   
      * @param w  Ignored.
 320   
      *
 321   
      * @return the task specified by the given unknown element, or
 322   
      *         <code>null</code> if the task name is not recognised.
 323   
      */
 324  3235
     protected Task makeTask(UnknownElement ue, RuntimeConfigurable w) {
 325  3235
         Task task = getProject().createTask(ue.getTag());
 326   
 
 327  3235
         if (task != null) {
 328  3062
             task.setLocation(getLocation());
 329   
             // UnknownElement always has an associated target
 330  3062
             task.setOwningTarget(getOwningTarget());
 331  3062
             task.init();
 332   
         }
 333  3235
         return task;
 334   
     }
 335   
 
 336   
     /**
 337   
      * Returns a very verbose exception for when a task/data type cannot
 338   
      * be found.
 339   
      *
 340   
      * @param what The kind of thing being created. For example, when
 341   
      *             a task name could not be found, this would be
 342   
      *             <code>"task"</code>. Should not be <code>null</code>.
 343   
      * @param elementName The name of the element which could not be found.
 344   
      *                    Should not be <code>null</code>.
 345   
      *
 346   
      * @return a detailed description of what might have caused the problem.
 347   
      */
 348  1
     protected BuildException getNotFoundException(String what,
 349   
                                                   String elementName) {
 350  1
         String lSep = System.getProperty("line.separator");
 351  1
         String msg = "Could not create " + what + " of type: " + elementName
 352   
             + "." + lSep + lSep
 353   
             + "Ant could not find the task or a class this "
 354   
             + "task relies upon." + lSep + lSep
 355   
             + "This is common and has a number of causes; the usual " + lSep
 356   
             + "solutions are to read the manual pages then download and" + lSep
 357   
             + "install needed JAR files, or fix the build file: " + lSep
 358   
             + " - You have misspelt '" + elementName + "'." + lSep
 359   
             + "   Fix: check your spelling." + lSep
 360   
             + " - The task needs an external JAR file to execute" + lSep
 361   
             + "   and this is not found at the right place in the classpath." + lSep
 362   
             + "   Fix: check the documentation for dependencies." + lSep
 363   
             + "   Fix: declare the task." + lSep
 364   
             + " - The task is an Ant optional task and optional.jar is absent" + lSep
 365   
             + "   Fix: look for optional.jar in ANT_HOME/lib, download if needed" + lSep
 366   
             + " - The task was not built into optional.jar as dependent"  + lSep
 367   
             + "   libraries were not found at build time." + lSep
 368   
             + "   Fix: look in the JAR to verify, then rebuild with the needed" + lSep
 369   
             + "   libraries, or download a release version from apache.org" + lSep
 370   
             + " - The build file was written for a later version of Ant" + lSep
 371   
             + "   Fix: upgrade to at least the latest release version of Ant" + lSep
 372   
             + " - The task is not an Ant core or optional task " + lSep
 373   
             + "   and needs to be declared using <taskdef>." + lSep
 374   
             + lSep
 375   
             + "Remember that for JAR files to be visible to Ant tasks implemented" + lSep
 376   
             + "in ANT_HOME/lib, the files must be in the same directory or on the" + lSep
 377   
             + "classpath" + lSep
 378   
             + lSep
 379   
             + "Please neither file bug reports on this problem, nor email the" + lSep
 380   
             + "Ant mailing lists, until all of these causes have been explored," + lSep
 381   
             + "as this is not an Ant bug.";
 382   
 
 383   
 
 384  1
         return new BuildException(msg, getLocation());
 385   
     }
 386   
 
 387   
     /**
 388   
      * Returns the name to use in logging messages.
 389   
      *
 390   
      * @return the name to use in logging messages.
 391   
      */
 392  22091
     public String getTaskName() {
 393   
         //return elementName;
 394  22091
         return realThing == null || !(realThing instanceof Task) ?
 395   
             super.getTaskName() : ((Task) realThing).getTaskName();
 396   
     }
 397   
 
 398   
     /**
 399   
      * Returns the task instance after it has been created and if it is a task.
 400   
      *
 401   
      * @return a task instance or <code>null</code> if the real object is not
 402   
      *         a task.
 403   
      */
 404  2
     public Task getTask() {
 405  2
         if (realThing instanceof Task) {
 406  2
             return (Task) realThing;
 407   
         }
 408  0
         return null;
 409   
     }
 410   
 
 411   
 }// UnknownElement
 412