Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 663   Methods: 25
NCLOC: 360   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ComponentHelper.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 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 org.apache.tools.ant.util.LazyHashtable;
 58   
 import org.apache.tools.ant.util.WeakishReference;
 59   
 
 60   
 import java.util.Enumeration;
 61   
 import java.util.Hashtable;
 62   
 import java.util.Properties;
 63   
 import java.util.Vector;
 64   
 import java.io.InputStream;
 65   
 import java.io.IOException;
 66   
 import java.lang.reflect.Modifier;
 67   
 
 68   
 /** 
 69   
  * Component creation and configuration.
 70   
  *
 71   
  * This is cut&paste from Project.java of everything related to
 72   
  * task/type management. Project will just delegate.
 73   
  * 
 74   
  * A very simple hook mechnism is provided that allows users to plug
 75   
  * in custom code. It is also possible to replace the default behavior
 76   
  * ( for example in an app embeding ant )
 77   
  *
 78   
  * @author Costin Manolache
 79   
  * @since Ant1.6
 80   
  */
 81   
 public class ComponentHelper  {
 82   
     /** Map from data type names to implementing classes (String to Class). */
 83   
     private Hashtable dataClassDefinitions;
 84   
     /** Map from task names to implementing classes (String to Class). */
 85   
     private Hashtable taskClassDefinitions;
 86   
     /**
 87   
      * Map from task names to vectors of created tasks
 88   
      * (String to Vector of Task). This is used to invalidate tasks if
 89   
      * the task definition changes.
 90   
      */
 91   
     private Hashtable createdTasks = new Hashtable();
 92   
 
 93   
 
 94   
     protected ComponentHelper next;
 95   
     protected Project project;
 96   
 
 97   
     /**
 98   
      */
 99  0
     public static ComponentHelper getComponentHelper(Project project) {
 100   
         // Singleton for now, it may change ( per/classloader )
 101  0
         ComponentHelper ph=(ComponentHelper)project.getReference( "ant.ComponentHelper" );
 102  0
         if( ph!=null ) return ph;
 103  0
         ph=new ComponentHelper();
 104  0
         ph.setProject( project );
 105   
 
 106  0
         project.addReference( "ant.ComponentHelper",ph );
 107  0
         return ph;
 108   
     }
 109   
 
 110  0
     protected ComponentHelper() {
 111   
     }
 112   
 
 113  0
     public void setNext( ComponentHelper next ) {
 114  0
         this.next=next;
 115   
     }
 116   
 
 117  0
     public ComponentHelper getNext() {
 118  0
         return next;
 119   
     }
 120   
 
 121  0
     public void setProject(Project project) {
 122  0
         this.project = project;
 123  0
         dataClassDefinitions= new AntTaskTable(project, false);
 124  0
         taskClassDefinitions= new AntTaskTable(project, true);
 125   
     }
 126   
 
 127   
 
 128   
     /** Creates an ant component..
 129   
      *
 130   
      * A factory may have knowledge about the tasks it creates. It can return
 131   
      * an object extending TaskAdapter that emulates Task/DataType. If null is returned,
 132   
      * the next helper is tried.
 133   
      *
 134   
      * @param ns namespace if a SAX2 parser is used, null for 'classical' ant
 135   
      * @param taskName the (local) name of the task.
 136   
      */
 137  0
     public Object createComponent( String ns,
 138   
                                    String taskName )
 139   
             throws BuildException
 140   
     {
 141  0
         if( getNext() != null ) {
 142  0
             return getNext().createComponent( ns, taskName);
 143   
         }
 144  0
         return null;
 145   
         // XXX class loader ? Can use the ns, but additional hints may be available in taskdef
 146   
         //
 147   
     }
 148   
 
 149  0
     public Object createComponent( UnknownElement ue,
 150   
                                    String ns,
 151   
                                    String taskName )
 152   
             throws BuildException
 153   
     {
 154  0
         Object component=null;
 155   
 
 156   
         // System.out.println("Fallback to project default " + taskName );
 157   
         // Can't create component. Default is to use the old methods in project.
 158   
 
 159   
         // This policy is taken from 1.5 ProjectHelper. In future the difference between
 160   
         // task and type should disapear.
 161  0
         if( project.getDataTypeDefinitions().get(taskName) != null ) {
 162   
             // This is the original policy in ProjectHelper. The 1.5 version of UnkwnonwElement
 163   
             // used to try first to create a task, and if it failed tried a type. In 1.6 the diff
 164   
             // should disapear.
 165  0
             component = project.createDataType(taskName);
 166  0
             if( component!=null ) return component;
 167   
         }
 168   
 
 169   
         // from UnkwnonwElement.createTask. The 'top level' case is removed, we're
 170   
         // allways lazy
 171  0
         component = project.createTask(taskName);
 172   
 
 173  0
         return component;
 174   
     }
 175   
 
 176  0
     public void initDefaultDefinitions() throws BuildException {
 177  0
         String defs = "/org/apache/tools/ant/taskdefs/defaults.properties";
 178   
 
 179  0
         try {
 180  0
             Properties props = new Properties();
 181  0
             InputStream in = this.getClass().getResourceAsStream(defs);
 182  0
             if (in == null) {
 183  0
                 throw new BuildException("Can't load default task list");
 184   
             }
 185  0
             props.load(in);
 186  0
             in.close();
 187  0
             ((AntTaskTable)taskClassDefinitions).addDefinitions( props );
 188   
 
 189   
 
 190   
         } catch (IOException ioe) {
 191  0
             throw new BuildException("Can't load default task list");
 192   
         }
 193   
 
 194  0
         String dataDefs = "/org/apache/tools/ant/types/defaults.properties";
 195   
 
 196  0
         try {
 197  0
             Properties props = new Properties();
 198  0
             InputStream in = this.getClass().getResourceAsStream(dataDefs);
 199  0
             if (in == null) {
 200  0
                 throw new BuildException("Can't load default datatype list");
 201   
             }
 202  0
             props.load(in);
 203  0
             in.close();
 204   
 
 205  0
             ((AntTaskTable)dataClassDefinitions).addDefinitions(props);
 206   
 
 207   
 
 208   
         } catch (IOException ioe) {
 209  0
             throw new BuildException("Can't load default datatype list");
 210   
         }
 211   
     }
 212   
 
 213   
     /**
 214   
      * Adds a new task definition to the project.
 215   
      * Attempting to override an existing definition with an
 216   
      * equivalent one (i.e. with the same classname) results in
 217   
      * a verbose log message. Attempting to override an existing definition
 218   
      * with a different one results in a warning log message and
 219   
      * invalidates any tasks which have already been created with the
 220   
      * old definition.
 221   
      *
 222   
      * @param taskName The name of the task to add.
 223   
      *                 Must not be <code>null</code>.
 224   
      * @param taskClass The full name of the class implementing the task.
 225   
      *                  Must not be <code>null</code>.
 226   
      *
 227   
      * @exception BuildException if the class is unsuitable for being an Ant
 228   
      *                           task. An error level message is logged before
 229   
      *                           this exception is thrown.
 230   
      *
 231   
      * @see #checkTaskClass(Class)
 232   
      -         */
 233  0
     public void addTaskDefinition(String taskName, Class taskClass)
 234   
             throws BuildException {
 235  0
         Class old = (Class) taskClassDefinitions.get(taskName);
 236  0
         if (null != old) {
 237  0
             if (old.equals(taskClass)) {
 238   
 //                project.log("Ignoring override for task " + taskName
 239   
 //                        + ", it is already defined by the same class.",
 240   
 //                        Project.MSG_VERBOSE);
 241  0
                 return;
 242   
             } else {
 243  0
                 int logLevel = Project.MSG_WARN;
 244  0
                 if (old.getName().equals(taskClass.getName())) {
 245  0
                     ClassLoader oldLoader = old.getClassLoader();
 246  0
                     ClassLoader newLoader = taskClass.getClassLoader();
 247   
                     // system classloader on older JDKs can be null
 248  0
                     if (oldLoader != null
 249   
                             && newLoader != null
 250   
                             && oldLoader instanceof AntClassLoader
 251   
                             && newLoader instanceof AntClassLoader
 252   
                             && ((AntClassLoader) oldLoader).getClasspath()
 253   
                             .equals(((AntClassLoader) newLoader).getClasspath())
 254   
                     ) {
 255   
                         // same classname loaded from the same
 256   
                         // classpath components
 257  0
                         logLevel = Project.MSG_VERBOSE;
 258   
                     }
 259   
                 }
 260   
 
 261  0
                 project.log("Trying to override old definition of task " + taskName,
 262   
                         logLevel);
 263  0
                 invalidateCreatedTasks(taskName);
 264   
             }
 265   
         }
 266   
 
 267  0
         String msg = " +User task: " + taskName + "     " + taskClass.getName();
 268  0
         project.log(msg, Project.MSG_DEBUG);
 269  0
         checkTaskClass(taskClass);
 270  0
         taskClassDefinitions.put(taskName, taskClass);
 271   
     }
 272   
 
 273   
     /**
 274   
      * Checks whether or not a class is suitable for serving as Ant task.
 275   
      * Ant task implementation classes must be public, concrete, and have
 276   
      * a no-arg constructor.
 277   
      *
 278   
      * @param taskClass The class to be checked.
 279   
      *                  Must not be <code>null</code>.
 280   
      *
 281   
      * @exception BuildException if the class is unsuitable for being an Ant
 282   
      *                           task. An error level message is logged before
 283   
      *                           this exception is thrown.
 284   
      */
 285  0
     public void checkTaskClass(final Class taskClass) throws BuildException {
 286  0
         if (!Modifier.isPublic(taskClass.getModifiers())) {
 287  0
             final String message = taskClass + " is not public";
 288  0
             project.log(message, Project.MSG_ERR);
 289  0
             throw new BuildException(message);
 290   
         }
 291  0
         if (Modifier.isAbstract(taskClass.getModifiers())) {
 292  0
             final String message = taskClass + " is abstract";
 293  0
             project.log(message, Project.MSG_ERR);
 294  0
             throw new BuildException(message);
 295   
         }
 296  0
         try {
 297  0
             taskClass.getConstructor(null);
 298   
             // don't have to check for public, since
 299   
             // getConstructor finds public constructors only.
 300   
         } catch (NoSuchMethodException e) {
 301  0
             final String message = "No public no-arg constructor in "
 302   
                     + taskClass;
 303  0
             project.log(message, Project.MSG_ERR);
 304  0
             throw new BuildException(message);
 305   
         }
 306  0
         if (!Task.class.isAssignableFrom(taskClass)) {
 307  0
             TaskAdapter.checkTaskClass(taskClass, project);
 308   
         }
 309   
     }
 310   
 
 311   
     /**
 312   
      * Returns the current task definition hashtable. The returned hashtable is
 313   
      * "live" and so should not be modified.
 314   
      *
 315   
      * @return a map of from task name to implementing class
 316   
      *         (String to Class).
 317   
      */
 318  0
     public Hashtable getTaskDefinitions() {
 319  0
         return taskClassDefinitions;
 320   
     }
 321   
 
 322   
     /**
 323   
      * Adds a new datatype definition.
 324   
      * Attempting to override an existing definition with an
 325   
      * equivalent one (i.e. with the same classname) results in
 326   
      * a verbose log message. Attempting to override an existing definition
 327   
      * with a different one results in a warning log message, but the
 328   
      * definition is changed.
 329   
      *
 330   
      * @param typeName The name of the datatype.
 331   
      *                 Must not be <code>null</code>.
 332   
      * @param typeClass The full name of the class implementing the datatype.
 333   
      *                  Must not be <code>null</code>.
 334   
      */
 335  0
     public void addDataTypeDefinition(String typeName, Class typeClass) {
 336  0
         synchronized(dataClassDefinitions) {
 337  0
             Class old = (Class) dataClassDefinitions.get(typeName);
 338  0
             if (null != old) {
 339  0
                 if (old.equals(typeClass)) {
 340   
 //                    project.log("Ignoring override for datatype " + typeName
 341   
 //                            + ", it is already defined by the same class.",
 342   
 //                            Project.MSG_VERBOSE);
 343  0
                     return;
 344   
                 } else {
 345  0
                     project.log("Trying to override old definition of datatype "
 346   
                             + typeName, Project.MSG_WARN);
 347   
                 }
 348   
             }
 349  0
             dataClassDefinitions.put(typeName, typeClass);
 350   
         }
 351  0
         String msg = " +User datatype: " + typeName + "     "
 352   
                 + typeClass.getName();
 353  0
         project.log(msg, Project.MSG_DEBUG);
 354   
     }
 355   
 
 356   
     /**
 357   
      * Returns the current datatype definition hashtable. The returned
 358   
      * hashtable is "live" and so should not be modified.
 359   
      *
 360   
      * @return a map of from datatype name to implementing class
 361   
      *         (String to Class).
 362   
      */
 363  0
     public Hashtable getDataTypeDefinitions() {
 364  0
         return dataClassDefinitions;
 365   
     }
 366   
 
 367   
     /**
 368   
      * Creates a new instance of a task, adding it to a list of
 369   
      * created tasks for later invalidation. This causes all tasks
 370   
      * to be remembered until the containing project is removed
 371   
      * @param taskType The name of the task to create an instance of.
 372   
      *                 Must not be <code>null</code>.
 373   
      *
 374   
      * @return an instance of the specified task, or <code>null</code> if
 375   
      *         the task name is not recognised.
 376   
      *
 377   
      * @exception BuildException if the task name is recognised but task
 378   
      *                           creation fails.
 379   
      */
 380  0
     public Task createTask(String taskType) throws BuildException {
 381  0
         Task task=createNewTask(taskType);
 382  0
         if(task!=null) {
 383  0
             addCreatedTask(taskType, task);
 384   
         }
 385  0
         return task;
 386   
     }
 387   
 
 388   
     /**
 389   
      * Creates a new instance of a task. This task is not
 390   
      * cached in the createdTasks list.
 391   
      * @since ant1.6
 392   
      * @param taskType The name of the task to create an instance of.
 393   
      *                 Must not be <code>null</code>.
 394   
      *
 395   
      * @return an instance of the specified task, or <code>null</code> if
 396   
      *         the task name is not recognised.
 397   
      *
 398   
      * @exception BuildException if the task name is recognised but task
 399   
      *                           creation fails.
 400   
      */
 401  0
     private Task createNewTask(String taskType) throws BuildException {
 402  0
         Class c = (Class) taskClassDefinitions.get(taskType);
 403   
 
 404  0
         if (c == null) {
 405  0
             return null;
 406   
         }
 407   
 
 408  0
         try {
 409  0
             Object o = c.newInstance();
 410  0
             Task task = null;
 411  0
             if (o instanceof Task) {
 412  0
                 task = (Task) o;
 413   
             } else {
 414   
                 // "Generic" Bean - use the setter pattern
 415   
                 // and an Adapter
 416  0
                 TaskAdapter taskA = new TaskAdapter();
 417  0
                 taskA.setProxy(o);
 418  0
                 task = taskA;
 419   
             }
 420  0
             task.setProject(project);
 421  0
             task.setTaskType(taskType);
 422   
 
 423   
             // set default value, can be changed by the user
 424  0
             task.setTaskName(taskType);
 425   
 
 426  0
             String msg = "   +Task: " + taskType;
 427  0
             project.log (msg, Project.MSG_DEBUG);
 428  0
             return task;
 429   
         } catch (Throwable t) {
 430  0
             System.out.println("task CL=" + c.getClassLoader());
 431  0
             String msg = "Could not create task of type: "
 432   
                     + taskType + " due to " + t;
 433  0
             throw new BuildException(msg, t);
 434   
         }
 435   
     }
 436   
 
 437   
     /**
 438   
      * Keeps a record of all tasks that have been created so that they
 439   
      * can be invalidated if a new task definition overrides the current one.
 440   
      *
 441   
      * @param type The name of the type of task which has been created.
 442   
      *             Must not be <code>null</code>.
 443   
      *
 444   
      * @param task The freshly created task instance.
 445   
      *             Must not be <code>null</code>.
 446   
      */
 447  0
     private void addCreatedTask(String type, Task task) {
 448  0
         synchronized (createdTasks) {
 449  0
             Vector v = (Vector) createdTasks.get(type);
 450  0
             if (v == null) {
 451  0
                 v = new Vector();
 452  0
                 createdTasks.put(type, v);
 453   
             }
 454  0
             v.addElement(WeakishReference.createReference(task));
 455   
         }
 456   
     }
 457   
 
 458   
     /**
 459   
      * Mark tasks as invalid which no longer are of the correct type
 460   
      * for a given taskname.
 461   
      *
 462   
      * @param type The name of the type of task to invalidate.
 463   
      *             Must not be <code>null</code>.
 464   
      */
 465  0
     private void invalidateCreatedTasks(String type) {
 466  0
         synchronized (createdTasks) {
 467  0
             Vector v = (Vector) createdTasks.get(type);
 468  0
             if (v != null) {
 469  0
                 Enumeration enum = v.elements();
 470  0
                 while (enum.hasMoreElements()) {
 471  0
                     WeakishReference ref=
 472   
                             (WeakishReference) enum.nextElement();
 473  0
                     Task t = (Task) ref.get();
 474   
                     //being a weak ref, it may be null by this point
 475  0
                     if(t!=null) {
 476  0
                         t.markInvalid();
 477   
                     }
 478   
                 }
 479  0
                 v.removeAllElements();
 480  0
                 createdTasks.remove(type);
 481   
             }
 482   
         }
 483   
     }
 484   
 
 485   
     /**
 486   
      * Creates a new instance of a data type.
 487   
      *
 488   
      * @param typeName The name of the data type to create an instance of.
 489   
      *                 Must not be <code>null</code>.
 490   
      *
 491   
      * @return an instance of the specified data type, or <code>null</code> if
 492   
      *         the data type name is not recognised.
 493   
      *
 494   
      * @exception BuildException if the data type name is recognised but
 495   
      *                           instance creation fails.
 496   
      */
 497  0
     public Object createDataType(String typeName) throws BuildException {
 498  0
         Class c = (Class) dataClassDefinitions.get(typeName);
 499   
 
 500  0
         if (c == null) {
 501  0
             return null;
 502   
         }
 503   
 
 504  0
         try {
 505  0
             java.lang.reflect.Constructor ctor = null;
 506  0
             boolean noArg = false;
 507   
             // DataType can have a "no arg" constructor or take a single
 508   
             // Project argument.
 509  0
             try {
 510  0
                 ctor = c.getConstructor(new Class[0]);
 511  0
                 noArg = true;
 512   
             } catch (NoSuchMethodException nse) {
 513  0
                 ctor = c.getConstructor(new Class[] {Project.class});
 514  0
                 noArg = false;
 515   
             }
 516   
 
 517  0
             Object o = null;
 518  0
             if (noArg) {
 519  0
                 o = ctor.newInstance(new Object[0]);
 520   
             } else {
 521  0
                 o = ctor.newInstance(new Object[] {this});
 522   
             }
 523  0
             if (o instanceof ProjectComponent) {
 524  0
                 ((ProjectComponent) o).setProject(project);
 525   
             }
 526  0
             String msg = "   +DataType: " + typeName;
 527  0
             project.log(msg, Project.MSG_DEBUG);
 528  0
             return o;
 529   
         } catch (java.lang.reflect.InvocationTargetException ite) {
 530  0
             Throwable t = ite.getTargetException();
 531  0
             String msg = "Could not create datatype of type: "
 532   
                     + typeName + " due to " + t;
 533  0
             throw new BuildException(msg, t);
 534   
         } catch (Throwable t) {
 535  0
             String msg = "Could not create datatype of type: "
 536   
                     + typeName + " due to " + t;
 537  0
             throw new BuildException(msg, t);
 538   
         }
 539   
     }
 540   
 
 541   
     /**
 542   
      * Returns a description of the type of the given element, with
 543   
      * special handling for instances of tasks and data types.
 544   
      * <p>
 545   
      * This is useful for logging purposes.
 546   
      *
 547   
      * @param element The element to describe.
 548   
      *                Must not be <code>null</code>.
 549   
      *
 550   
      * @return a description of the element type
 551   
      *
 552   
      * @since Ant 1.6
 553   
      */
 554  0
     public String getElementName(Object element) {
 555  0
         Hashtable elements = taskClassDefinitions;
 556  0
         Class elementClass = element.getClass();
 557  0
         String typeName = "task";
 558  0
         if (!elements.contains(elementClass)) {
 559  0
             elements = dataClassDefinitions;
 560  0
             typeName = "data type";
 561  0
             if (!elements.contains(elementClass)) {
 562  0
                 elements = null;
 563   
             }
 564   
         }
 565   
 
 566  0
         if (elements != null) {
 567  0
             Enumeration e = elements.keys();
 568  0
             while (e.hasMoreElements()) {
 569  0
                 String name = (String) e.nextElement();
 570  0
                 Class clazz = (Class) elements.get(name);
 571  0
                 if (elementClass.equals(clazz)) {
 572  0
                     return "The <" + name + "> " + typeName;
 573   
                 }
 574   
             }
 575   
         }
 576   
 
 577  0
         return "Class " + elementClass.getName();
 578   
     }
 579   
 
 580   
 
 581   
     private static class AntTaskTable extends LazyHashtable {
 582   
         Project project;
 583   
         Properties props;
 584   
         boolean tasks=false;
 585   
 
 586  0
         public AntTaskTable( Project p, boolean tasks ) {
 587  0
             this.project=p;
 588  0
             this.tasks=tasks;
 589   
         }
 590   
 
 591  0
         public void addDefinitions( Properties props ) {
 592  0
             this.props=props;
 593   
         }
 594   
 
 595  0
         protected void initAll( ) {
 596  0
             if( initAllDone ) return;
 597  0
             project.log("InitAll", Project.MSG_DEBUG);
 598  0
             if( props==null ) return;
 599  0
             Enumeration enum = props.propertyNames();
 600  0
             while (enum.hasMoreElements()) {
 601  0
                 String key = (String) enum.nextElement();
 602  0
                 Class taskClass=getTask( key );
 603  0
                 if( taskClass!=null ) {
 604   
                     // This will call a get() and a put()
 605  0
                     if( tasks )
 606  0
                         project.addTaskDefinition(key, taskClass);
 607   
                     else
 608  0
                         project.addDataTypeDefinition(key, taskClass );
 609   
                 }
 610   
             }
 611  0
             initAllDone=true;
 612   
         }
 613   
 
 614  0
         protected Class getTask(String key) {
 615  0
             if( props==null ) return null; // for tasks loaded before init()
 616  0
             String value=props.getProperty(key);
 617  0
             if( value==null) {
 618   
                 //project.log( "No class name for " + key, Project.MSG_VERBOSE );
 619  0
                 return null;
 620   
             }
 621  0
             try {
 622  0
                 Class taskClass=null;
 623  0
                 if( project.getCoreLoader() != null &&
 624   
                     !("only".equals(project.getProperty("build.sysclasspath")))) {
 625  0
                     try {
 626  0
                         project.log("Loading with the core loader " + value,
 627   
                                 Project.MSG_DEBUG);
 628  0
                         taskClass=project.getCoreLoader().loadClass(value);
 629  0
                         if( taskClass != null ) return taskClass;
 630   
                     } catch( Exception ex ) {
 631   
                     }
 632   
                 }
 633  0
                 taskClass = Class.forName(value);
 634  0
                 return taskClass;
 635   
             } catch (NoClassDefFoundError ncdfe) {
 636  0
                 project.log("Could not load a dependent class ("
 637   
                         + ncdfe.getMessage() + ") for task " + key, Project.MSG_DEBUG);
 638   
             } catch (ClassNotFoundException cnfe) {
 639  0
                 project.log("Could not load class (" + value
 640   
                         + ") for task " + key, Project.MSG_DEBUG);
 641   
             }
 642  0
             return null;
 643   
         }
 644   
 
 645   
         // Hashtable implementation
 646  0
         public Object get( Object key ) {
 647  0
             Object orig=super.get( key );
 648  0
             if( orig!= null ) return orig;
 649  0
             if( ! (key instanceof String) ) return null;
 650  0
             project.log("Get task " + key, Project.MSG_DEBUG );
 651  0
             Object taskClass=getTask( (String) key);
 652  0
             if( taskClass != null)
 653  0
                 super.put( key, taskClass );
 654  0
             return taskClass;
 655   
         }
 656   
 
 657  0
         public boolean contains( Object key ) {
 658  0
             return get( key ) != null;
 659   
         }
 660   
 
 661   
     }
 662   
 }
 663